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

Commit 5b1b7344 authored by Jiyong Park's avatar Jiyong Park Committed by Jeff Hamilton
Browse files

Fix: PackageInfo for apex has wrong info

Currently, ApexInfo.packageName is directly fed into PackageInfo. However,
this is wrong because ApexInfo.packageName is from apex_manifest.json,
not AndroidManifest.xml. Name in apex_manifest.json is the internal ID
of an APEX while the name in AndroidManifest.xml is the public
externally-visible name.

Fixing the issue by parsing the AndroidManifest.xml in the apex file
via PackageParser.

This change also fixes the problem that signature is not included in the
PackageInfo for APEX. It is included when GET_SIGNATURES is specified.

Bug: 123029986
Bug: 123028426
Test: adb shell cmd package list packages --apex-only --show-versioncode
Shows com.google.* names

Change-Id: I0021b302f3f4e843f79dd6d40716cefd531c5628
parent 73dd7c91
Loading
Loading
Loading
Loading
+0 −10
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package android.content.pm;

import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.apex.ApexInfo;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -573,15 +572,6 @@ public class PackageInfo implements Parcelable {
        }
    }

    /**
     * @hide
     */
    public PackageInfo(ApexInfo apexInfo) {
        packageName = apexInfo.packageName;
        setLongVersionCode(apexInfo.versionCode);
        isApex = true;
    }

    private void propagateApplicationInfo(ApplicationInfo appInfo, ComponentInfo[] components) {
        if (components != null) {
            for (ComponentInfo ci : components) {
+38 −0
Original line number Diff line number Diff line
@@ -8484,4 +8484,42 @@ public class PackageParser {
            this.error = error;
        }
    }

    public static PackageInfo generatePackageInfoFromApex(File apexFile, boolean collectCerts)
            throws PackageParserException {
        PackageInfo pi = new PackageInfo();
        // TODO(b/123052859): We should avoid these repeated calls to parseApkLite each time
        // we want to generate information for APEX modules.
        PackageParser.ApkLite apk = PackageParser.parseApkLite(apexFile,
            collectCerts ? PackageParser.PARSE_COLLECT_CERTIFICATES : 0);

        pi.packageName = apk.packageName;
        pi.setLongVersionCode(apk.getLongVersionCode());

        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) {
                // only return a valid SigningInfo if there is signing information to report
                pi.signingInfo = new SigningInfo(apk.signingDetails);
            } else {
                pi.signingInfo = null;
            }
        }

        pi.isApex = true;
        return pi;
    }
}
+1.23 MiB

File added.

No diff preview for this file type.

+43 −5
Original line number Diff line number Diff line
@@ -329,6 +329,28 @@ public class PackageParserTest {
        return parsePackage(apkFileName, apkResourceId, p -> p);
    }

    /**
     * Copies a specified {@code resourceId} to a file. Returns a non-null file if the copy
     * succeeded, or {@code null} otherwise.
     */
    File copyRawResourceToFile(String baseName, int resourceId) throws Exception {
        // Copy the resource to a file.
        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        InputStream is = context.getResources().openRawResource(resourceId);
        File outFile = null;
        try {
            outFile = new File(context.getFilesDir(), baseName);
            assertTrue(FileUtils.copyToFile(is, outFile));
            return outFile;
        } catch (Exception e) {
            if (outFile != null) {
                outFile.delete();
            }

            return null;
        }
    }

    /**
     * Attempts to parse a package.
     *
@@ -340,16 +362,16 @@ public class PackageParserTest {
    Package parsePackage(String apkFileName, int apkResourceId,
            Function<Package, Package> converter) throws Exception {
        // Copy the resource to a file.
        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        File outFile = new File(context.getFilesDir(), apkFileName);
        File outFile = null;
        try {
            InputStream is = context.getResources().openRawResource(apkResourceId);
            assertTrue(FileUtils.copyToFile(is, outFile));
            outFile = copyRawResourceToFile(apkFileName, apkResourceId);
            return converter.apply(new PackageParser().parsePackage(outFile, 0 /* flags */));
        } finally {
            if (outFile != null) {
                outFile.delete();
            }
        }
    }

    /**
     * Asserts basic properties about a component.
@@ -498,4 +520,20 @@ public class PackageParserTest {
                        "android.permission.READ_CONTACTS"),
                secondChild.requestedPermissions);
    }

    @Test
    public void testApexPackageInfoGeneration() throws Exception {
        File apexFile = copyRawResourceToFile("com.android.tzdata.apex",
                R.raw.com_android_tzdata);
        PackageInfo pi = PackageParser.generatePackageInfoFromApex(apexFile, false);
        assertEquals("com.google.android.tzdata", pi.packageName);
        assertEquals(1, pi.getLongVersionCode());
        assertNull(pi.signingInfo);

        pi = PackageParser.generatePackageInfoFromApex(apexFile, true);
        assertEquals("com.google.android.tzdata", pi.packageName);
        assertEquals(1, pi.getLongVersionCode());
        assertNotNull(pi.signingInfo);
        assertTrue(pi.signingInfo.getApkContentsSigners().length > 0);
    }
}
+7 −2
Original line number Diff line number Diff line
@@ -7883,8 +7883,13 @@ public class PackageManagerService extends IPackageManager.Stub
                if (apex != null) {
                    try {
                        final ApexInfo[] activePkgs = apex.getActivePackages();
                        for (ApexInfo apexInfo : activePkgs) {
                            list.add(new PackageInfo(apexInfo));
                        for (ApexInfo ai : activePkgs) {
                            try {
                                 list.add(PackageParser.generatePackageInfoFromApex(
                                         new File(ai.packagePath), true /* collect certs */));
                            } catch (PackageParserException pe) {
                                 throw new IllegalStateException("Unable to parse: " + ai, pe);
                            }
                        }
                    } catch (RemoteException e) {
                        Log.e(TAG, "Unable to retrieve packages from apexservice: " + e.toString());