Loading core/java/android/content/pm/PackageInfo.java +0 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -578,15 +577,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) { Loading core/java/android/content/pm/PackageParser.java +38 −0 Original line number Diff line number Diff line Loading @@ -8490,4 +8490,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; } } core/tests/coretests/res/raw/com_android_tzdata.apex 0 → 100644 +1.23 MiB File added.No diff preview for this file type. View file core/tests/coretests/src/android/content/pm/PackageParserTest.java +43 −5 Original line number Diff line number Diff line Loading @@ -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. * Loading @@ -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. Loading Loading @@ -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); } } services/core/java/com/android/server/pm/PackageManagerService.java +7 −2 Original line number Diff line number Diff line Loading @@ -7892,8 +7892,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()); Loading
core/java/android/content/pm/PackageInfo.java +0 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -578,15 +577,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) { Loading
core/java/android/content/pm/PackageParser.java +38 −0 Original line number Diff line number Diff line Loading @@ -8490,4 +8490,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; } }
core/tests/coretests/res/raw/com_android_tzdata.apex 0 → 100644 +1.23 MiB File added.No diff preview for this file type. View file
core/tests/coretests/src/android/content/pm/PackageParserTest.java +43 −5 Original line number Diff line number Diff line Loading @@ -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. * Loading @@ -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. Loading Loading @@ -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); } }
services/core/java/com/android/server/pm/PackageManagerService.java +7 −2 Original line number Diff line number Diff line Loading @@ -7892,8 +7892,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());