Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20da56d2 authored by Mohammad Samiul Islam's avatar Mohammad Samiul Islam Committed by Android (Google) Code Review
Browse files

Merge "Improve PackageInfo parsing for apex files"

parents 3bb363fa 7aa7d2ee
Loading
Loading
Loading
Loading
+24 −59
Original line number Diff line number Diff line
@@ -4782,7 +4782,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;
        }
@@ -8359,71 +8359,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.ApkLite apk = PackageParser.parseApkLite(apexFile, parseFlags);

        // 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);
            }
        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);

        pi.applicationInfo.sourceDir = apexFile.getPath();
        pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_INSTALLED;
        pi.isApex = true;

            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;
    }
}
+8 −18
Original line number Diff line number Diff line
@@ -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);
    }
+3 −1
Original line number Diff line number Diff line
@@ -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);
                    }