diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index a4933ef1703f6..ef08bf53f5b0c 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -620,21 +620,6 @@ public class PackageParser { return path.endsWith(APK_FILE_EXTENSION); } - /** - * Generate and return the {@link PackageInfo} for a parsed package. - * - * @param p the parsed package. - * @param flags indicating which optional information is included. - */ - @UnsupportedAppUsage - public static PackageInfo generatePackageInfo(PackageParser.Package p, - int gids[], int flags, long firstInstallTime, long lastUpdateTime, - Set grantedPermissions, PackageUserState state) { - - return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime, - grantedPermissions, state, UserHandle.getCallingUserId()); - } - /** * Returns true if the package is installed and not hidden, or if the caller * explicitly wanted all uninstalled and hidden packages as well. @@ -661,8 +646,45 @@ public class PackageParser { return checkUseInstalledOrHidden(0, state, null); } + /** + * Generate and return the {@link PackageInfo} for a parsed package. + * + * @param p the parsed package. + * @param flags indicating which optional information is included. + */ @UnsupportedAppUsage public static PackageInfo generatePackageInfo(PackageParser.Package p, + int[] gids, int flags, long firstInstallTime, long lastUpdateTime, + Set grantedPermissions, PackageUserState state) { + + return generatePackageInfo(p, gids, flags, firstInstallTime, lastUpdateTime, + grantedPermissions, state, UserHandle.getCallingUserId()); + } + + @UnsupportedAppUsage + public static PackageInfo generatePackageInfo(PackageParser.Package p, + int[] gids, int flags, long firstInstallTime, long lastUpdateTime, + Set grantedPermissions, PackageUserState state, int userId) { + + return generatePackageInfo(p, null, gids, flags, firstInstallTime, lastUpdateTime, + grantedPermissions, state, userId); + } + + /** + * PackageInfo generator specifically for apex files. + * + * @param pkg Package to generate info from. Should be derived from an apex. + * @param apexInfo Apex info relating to the package. + * @return PackageInfo + * @throws PackageParserException + */ + public static PackageInfo generatePackageInfo( + PackageParser.Package pkg, ApexInfo apexInfo, int flags) { + return generatePackageInfo(pkg, apexInfo, EmptyArray.INT, flags, 0, 0, + Collections.emptySet(), new PackageUserState(), UserHandle.getCallingUserId()); + } + + private static PackageInfo generatePackageInfo(PackageParser.Package p, ApexInfo apexInfo, int gids[], int flags, long firstInstallTime, long lastUpdateTime, Set grantedPermissions, PackageUserState state, int userId) { if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) { @@ -809,8 +831,27 @@ public class PackageParser { } } } + + if (apexInfo != null) { + File apexFile = new File(apexInfo.modulePath); + + pi.applicationInfo.sourceDir = apexFile.getPath(); + pi.applicationInfo.publicSourceDir = apexFile.getPath(); + if (apexInfo.isFactory) { + pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; + } else { + pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; + } + if (apexInfo.isActive) { + pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; + } else { + pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; + } + pi.isApex = true; + } + // deprecated method of getting signing certificates - if ((flags&PackageManager.GET_SIGNATURES) != 0) { + if ((flags & PackageManager.GET_SIGNATURES) != 0) { if (p.mSigningDetails.hasPastSigningCertificates()) { // Package has included signing certificate rotation information. Return the oldest // cert so that programmatic checks keep working even if unaware of key rotation. @@ -8461,61 +8502,4 @@ public class PackageParser { } } - // TODO(b/129261524): Clean up API - /** - * PackageInfo parser specifically for apex files. - * NOTE: It will collect certificates - * - * @param apexInfo - * @return PackageInfo - * @throws PackageParserException - */ - public static PackageInfo generatePackageInfoFromApex(ApexInfo apexInfo, int flags) - throws PackageParserException { - PackageParser pp = new PackageParser(); - File apexFile = new File(apexInfo.modulePath); - final Package p = pp.parsePackage(apexFile, flags, false); - PackageUserState state = new PackageUserState(); - PackageInfo pi = generatePackageInfo(p, EmptyArray.INT, flags, 0, 0, - Collections.emptySet(), state); - pi.applicationInfo.sourceDir = apexFile.getPath(); - pi.applicationInfo.publicSourceDir = apexFile.getPath(); - if (apexInfo.isFactory) { - pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; - } else { - pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM; - } - if (apexInfo.isActive) { - pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED; - } else { - pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED; - } - pi.isApex = true; - - // Collect certificates - if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) { - collectCertificates(p, apexFile, false); - // Keep legacy mechanism for handling signatures. While this is deprecated, it's - // still part of the public API and needs to be maintained - if (p.mSigningDetails.hasPastSigningCertificates()) { - // Package has included signing certificate rotation information. Return - // the oldest cert so that programmatic checks keep working even if unaware - // of key rotation. - pi.signatures = new Signature[1]; - pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0]; - } else if (p.mSigningDetails.hasSignatures()) { - // otherwise keep old behavior - int numberOfSigs = p.mSigningDetails.signatures.length; - pi.signatures = new Signature[numberOfSigs]; - System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs); - } - if (p.mSigningDetails != SigningDetails.UNKNOWN) { - // only return a valid SigningInfo if there is signing information to report - pi.signingInfo = new SigningInfo(p.mSigningDetails); - } else { - pi.signingInfo = null; - } - } - return pi; - } } diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java index eb61e9cba64d0..5c7f2af782b9d 100644 --- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java +++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java @@ -520,7 +520,12 @@ public class PackageParserTest { apexInfo.modulePath = apexFile.getPath(); apexInfo.versionCode = 191000070; int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES; - PackageInfo pi = PackageParser.generatePackageInfoFromApex(apexInfo, flags); + + PackageParser pp = new PackageParser(); + Package p = pp.parsePackage(apexFile, flags, false); + PackageParser.collectCertificates(p, false); + PackageInfo pi = PackageParser.generatePackageInfo(p, apexInfo, flags); + assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName); assertTrue(pi.applicationInfo.enabled); assertEquals(28, pi.applicationInfo.targetSdkVersion); diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index dd099b15a4647..a1b6d492a4a39 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -282,30 +282,39 @@ abstract class ApexManager { if ((new File(ai.modulePath)).isDirectory()) { break; } + int flags = PackageManager.GET_META_DATA + | PackageManager.GET_SIGNING_CERTIFICATES + | PackageManager.GET_SIGNATURES; + PackageParser.Package pkg; try { - final PackageInfo pkg = PackageParser.generatePackageInfoFromApex( - ai, PackageManager.GET_META_DATA - | PackageManager.GET_SIGNING_CERTIFICATES); - mAllPackagesCache.add(pkg); - if (ai.isActive) { - if (activePackagesSet.contains(pkg.packageName)) { - throw new IllegalStateException( - "Two active packages have the same name: " - + pkg.packageName); - } - activePackagesSet.add(pkg.packageName); - } - if (ai.isFactory) { - if (factoryPackagesSet.contains(pkg.packageName)) { - throw new IllegalStateException( - "Two factory packages have the same name: " - + pkg.packageName); - } - factoryPackagesSet.add(pkg.packageName); - } + File apexFile = new File(ai.modulePath); + PackageParser pp = new PackageParser(); + pkg = pp.parsePackage(apexFile, flags, false); + PackageParser.collectCertificates(pkg, false); } catch (PackageParser.PackageParserException pe) { throw new IllegalStateException("Unable to parse: " + ai, pe); } + + final PackageInfo packageInfo = + PackageParser.generatePackageInfo(pkg, ai, flags); + mAllPackagesCache.add(packageInfo); + if (ai.isActive) { + if (activePackagesSet.contains(packageInfo.packageName)) { + throw new IllegalStateException( + "Two active packages have the same name: " + + packageInfo.packageName); + } + activePackagesSet.add(packageInfo.packageName); + } + if (ai.isFactory) { + if (factoryPackagesSet.contains(packageInfo.packageName)) { + throw new IllegalStateException( + "Two factory packages have the same name: " + + packageInfo.packageName); + } + factoryPackagesSet.add(packageInfo.packageName); + } + } } catch (RemoteException re) { Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString()); diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index bdeaf028bac89..6d3424cf39429 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -160,25 +160,29 @@ public class StagingManager { final ApexInfoList apexInfoList = mApexManager.submitStagedSession(session.sessionId, childSessionsIds.toArray()); final List result = new ArrayList<>(); - for (ApexInfo newPackage : apexInfoList.apexInfos) { - final PackageInfo pkg; + for (ApexInfo apexInfo : apexInfoList.apexInfos) { + final PackageInfo packageInfo; + int flags = PackageManager.GET_META_DATA; + PackageParser.Package pkg; try { - pkg = PackageParser.generatePackageInfoFromApex(newPackage, - PackageManager.GET_META_DATA); + File apexFile = new File(apexInfo.modulePath); + PackageParser pp = new PackageParser(); + pkg = pp.parsePackage(apexFile, flags, false); } catch (PackageParserException e) { throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, - "Failed to parse APEX package " + newPackage.modulePath, e); + "Failed to parse APEX package " + apexInfo.modulePath, e); } - final PackageInfo activePackage = mApexManager.getPackageInfo(pkg.packageName, + packageInfo = PackageParser.generatePackageInfo(pkg, apexInfo, flags); + final PackageInfo activePackage = mApexManager.getPackageInfo(packageInfo.packageName, ApexManager.MATCH_ACTIVE_PACKAGE); if (activePackage == null) { - Slog.w(TAG, "Attempting to install new APEX package " + pkg.packageName); + Slog.w(TAG, "Attempting to install new APEX package " + packageInfo.packageName); throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, "It is forbidden to install new APEX packages."); } checkRequiredVersionCode(session, activePackage); - checkDowngrade(session, activePackage, pkg); - result.add(pkg); + checkDowngrade(session, activePackage, packageInfo); + result.add(packageInfo); } Slog.d(TAG, "Session " + session.sessionId + " has following APEX packages: [" + result.stream().map(p -> p.packageName).collect(Collectors.joining(",")) + "]");