Improve PackageInfo parsing for apex files
"meta-data" in AndroidManifest was not getting parsed by the existing logic. Bug: 129091257 Test: atest android.content.pm.PackageParserTest Change-Id: I3d1c38ba3b2a0ccef6a0d7d0ee5ab857b62a7b82
This commit is contained in:
@@ -4796,7 +4796,7 @@ public class PackageParser {
|
||||
// except for watches which always supported 1:1.
|
||||
minAspectRatio = owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q
|
||||
? 0
|
||||
: mCallback.hasFeature(FEATURE_WATCH)
|
||||
: (mCallback != null && mCallback.hasFeature(FEATURE_WATCH))
|
||||
? DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH
|
||||
: DEFAULT_PRE_Q_MIN_ASPECT_RATIO;
|
||||
}
|
||||
@@ -8373,71 +8373,36 @@ public class PackageParser {
|
||||
}
|
||||
|
||||
// TODO(b/129261524): Clean up API
|
||||
public static PackageInfo generatePackageInfoFromApex(File apexFile, boolean collectCerts)
|
||||
/**
|
||||
* PackageInfo parser specifically for apex files.
|
||||
* NOTE: It will collect certificates
|
||||
*
|
||||
* @param apexFile
|
||||
* @return PackageInfo
|
||||
* @throws PackageParserException
|
||||
*/
|
||||
public static PackageInfo generatePackageInfoFromApex(File apexFile, int flags)
|
||||
throws PackageParserException {
|
||||
PackageInfo pi = new PackageInfo();
|
||||
int parseFlags = 0;
|
||||
if (collectCerts) {
|
||||
parseFlags |= PARSE_COLLECT_CERTIFICATES;
|
||||
try {
|
||||
if (apexFile.getCanonicalPath().startsWith("/system")) {
|
||||
// Don't need verify the APK integrity of APEXes on /system, just like
|
||||
// we don't do that for APKs.
|
||||
// TODO(b/126514108): we may be able to do this for APEXes on /data as well.
|
||||
parseFlags |= PARSE_IS_SYSTEM_DIR;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
|
||||
"Failed to get path for " + apexFile.getPath(), e);
|
||||
}
|
||||
}
|
||||
PackageParser pp = new PackageParser();
|
||||
final Package p = pp.parsePackage(apexFile, flags, false);
|
||||
PackageUserState state = new PackageUserState();
|
||||
PackageInfo pi = generatePackageInfo(p, EmptyArray.INT, flags, 0, 0,
|
||||
Collections.emptySet(), state);
|
||||
|
||||
PackageParser.ApkLite apk = PackageParser.parseApkLite(apexFile, parseFlags);
|
||||
pi.applicationInfo.sourceDir = apexFile.getPath();
|
||||
pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_INSTALLED;
|
||||
pi.isApex = true;
|
||||
|
||||
// Properly fill in the ApplicationInfo with data from AndroidManifest
|
||||
// Add ApplicationInfo to the PackageInfo.
|
||||
// TODO(b/129267599)
|
||||
ApplicationInfo ai = new ApplicationInfo();
|
||||
ai.packageName = apk.packageName;
|
||||
ai.sourceDir = apexFile.getPath();
|
||||
ai.flags = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_INSTALLED;
|
||||
ai.enabled = true;
|
||||
ai.minSdkVersion = apk.minSdkVersion;
|
||||
ai.targetSdkVersion = apk.targetSdkVersion;
|
||||
ai.targetSandboxVersion = PARSE_DEFAULT_TARGET_SANDBOX;
|
||||
ai.setVersionCode(apk.getLongVersionCode());
|
||||
|
||||
pi.packageName = apk.packageName;
|
||||
pi.splitNames = new String[]{apk.splitName};
|
||||
pi.setLongVersionCode(apk.getLongVersionCode());
|
||||
pi.applicationInfo = ai;
|
||||
pi.coreApp = apk.coreApp;
|
||||
|
||||
|
||||
if (collectCerts) {
|
||||
if (apk.signingDetails.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] = apk.signingDetails.pastSigningCertificates[0];
|
||||
} else if (apk.signingDetails.hasSignatures()) {
|
||||
// otherwise keep old behavior
|
||||
int numberOfSigs = apk.signingDetails.signatures.length;
|
||||
pi.signatures = new Signature[numberOfSigs];
|
||||
System.arraycopy(apk.signingDetails.signatures, 0, pi.signatures, 0,
|
||||
numberOfSigs);
|
||||
}
|
||||
|
||||
if (apk.signingDetails != SigningDetails.UNKNOWN) {
|
||||
// Collect certificates
|
||||
if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
|
||||
collectCertificates(p, apexFile, false);
|
||||
if (p.mSigningDetails != SigningDetails.UNKNOWN) {
|
||||
// only return a valid SigningInfo if there is signing information to report
|
||||
pi.signingInfo = new SigningInfo(apk.signingDetails);
|
||||
pi.signingInfo = new SigningInfo(p.mSigningDetails);
|
||||
} else {
|
||||
pi.signingInfo = null;
|
||||
}
|
||||
}
|
||||
|
||||
pi.isApex = true;
|
||||
return pi;
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -499,30 +499,20 @@ public class PackageParserTest {
|
||||
public void testApexPackageInfoGeneration() throws Exception {
|
||||
File apexFile = copyRawResourceToFile("com.android.tzdata.apex",
|
||||
R.raw.com_android_tzdata);
|
||||
PackageInfo pi = PackageParser.generatePackageInfoFromApex(apexFile, false);
|
||||
int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES;
|
||||
PackageInfo pi = PackageParser.generatePackageInfoFromApex(apexFile, flags);
|
||||
assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName);
|
||||
assertTrue(pi.applicationInfo.enabled);
|
||||
assertEquals(28, pi.applicationInfo.targetSdkVersion);
|
||||
assertEquals(1, pi.applicationInfo.longVersionCode);
|
||||
assertEquals(191000070, pi.applicationInfo.longVersionCode);
|
||||
assertNotNull(pi.applicationInfo.metaData);
|
||||
assertEquals(apexFile.getPath(), pi.applicationInfo.sourceDir);
|
||||
assertEquals("Bundle[{com.android.vending.derived.apk.id=1}]",
|
||||
pi.applicationInfo.metaData.toString());
|
||||
|
||||
assertEquals("com.google.android.tzdata", pi.packageName);
|
||||
assertTrue(pi.splitNames.length > 0);
|
||||
assertEquals(1, pi.getLongVersionCode());
|
||||
assertNull(pi.signingInfo);
|
||||
assertNull(pi.signatures);
|
||||
assertTrue(pi.isApex);
|
||||
|
||||
pi = PackageParser.generatePackageInfoFromApex(apexFile, true);
|
||||
assertEquals("com.google.android.tzdata", pi.applicationInfo.packageName);
|
||||
assertTrue(pi.applicationInfo.enabled);
|
||||
assertEquals(28, pi.applicationInfo.targetSdkVersion);
|
||||
assertEquals(1, pi.applicationInfo.longVersionCode);
|
||||
|
||||
assertEquals("com.google.android.tzdata", pi.packageName);
|
||||
assertTrue(pi.splitNames.length > 0);
|
||||
assertEquals(1, pi.getLongVersionCode());
|
||||
assertEquals(191000070, pi.getLongVersionCode());
|
||||
assertNotNull(pi.signingInfo);
|
||||
assertNotNull(pi.signatures);
|
||||
assertTrue(pi.signingInfo.getApkContentsSigners().length > 0);
|
||||
assertTrue(pi.isApex);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageParser;
|
||||
import android.content.pm.PackageParser.PackageParserException;
|
||||
import android.os.RemoteException;
|
||||
@@ -95,7 +96,8 @@ class ApexManager {
|
||||
}
|
||||
try {
|
||||
list.add(PackageParser.generatePackageInfoFromApex(
|
||||
new File(ai.packagePath), true /* collect certs */));
|
||||
new File(ai.packagePath), PackageManager.GET_META_DATA
|
||||
| PackageManager.GET_SIGNING_CERTIFICATES));
|
||||
} catch (PackageParserException pe) {
|
||||
throw new IllegalStateException("Unable to parse: " + ai, pe);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user