Loading services/core/java/com/android/server/pm/InstructionSets.java +8 −5 Original line number Diff line number Diff line Loading @@ -22,11 +22,11 @@ import android.os.SystemProperties; import android.text.TextUtils; import android.util.ArraySet; import dalvik.system.VMRuntime; import java.util.ArrayList; import java.util.List; import dalvik.system.VMRuntime; /** * Provides various methods for obtaining and converting of instruction sets. * Loading Loading @@ -113,12 +113,15 @@ public class InstructionSets { return allInstructionSets; } public static String getPrimaryInstructionSet(ApplicationInfo info) { if (info.primaryCpuAbi == null) { /** * Calculates the primary instruction set based on the computed Abis of a given package. */ public static String getPrimaryInstructionSet(PackageAbiHelper.Abis abis) { if (abis.primary == null) { return getPreferredInstructionSet(); } return VMRuntime.getInstructionSet(info.primaryCpuAbi); return VMRuntime.getInstructionSet(abis.primary); } } services/core/java/com/android/server/pm/PackageAbiHelper.java +80 −30 Original line number Diff line number Diff line Loading @@ -18,56 +18,44 @@ package com.android.server.pm; import android.annotation.Nullable; import android.content.pm.PackageParser; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import java.io.File; import java.util.List; import java.util.Set; @VisibleForTesting interface PackageAbiHelper { /** * Derive and set the location of native libraries for the given package, * Derive and get the location of native libraries for the given package, * which varies depending on where and how the package was installed. * * WARNING: This API enables modifying of the package. * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary */ void setNativeLibraryPaths(PackageParser.Package pkg, File appLib32InstallDir); NativeLibraryPaths getNativeLibraryPaths( PackageParser.Package pkg, File appLib32InstallDir); /** * Calculate the abis and roots for a bundled app. These can uniquely * be determined from the contents of the system partition, i.e whether * it contains 64 or 32 bit shared libraries etc. We do not validate any * of this information, and instead assume that the system was built * sensibly. * * WARNING: This API enables modifying of the package. * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary * Calculate the abis for a bundled app. These can uniquely be determined from the contents of * the system partition, i.e whether it contains 64 or 32 bit shared libraries etc. We do not * validate any of this information, and instead assume that the system was built sensibly. */ void setBundledAppAbisAndRoots(PackageParser.Package pkg, PackageSetting pkgSetting); Abis getBundledAppAbis(PackageParser.Package pkg); /** * Derive the ABI of a non-system package located at {@code scanFile}. This information * is derived purely on the basis of the contents of {@code scanFile} and * {@code cpuAbiOverride}. * Derive the ABI of a non-system package located at {@code pkg}. This information * is derived purely on the basis of the contents of {@code pkg} and {@code cpuAbiOverride}. * * If {@code extractLibs} is true, native libraries are extracted from the app if required. * * WARNING: This API enables modifying of the package. * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary */ void derivePackageAbi(PackageParser.Package pkg, String cpuAbiOverride, boolean extractLibs) Pair<Abis, NativeLibraryPaths> derivePackageAbi( PackageParser.Package pkg, String cpuAbiOverride, boolean extractLibs) throws PackageManagerException; /** * Adjusts ABIs for a set of packages belonging to a shared user so that they all match. * i.e, so that all packages can be run inside a single process if required. * Calculates adjusted ABIs for a set of packages belonging to a shared user so that they all * match. i.e, so that all packages can be run inside a single process if required. * * Optionally, callers can pass in a parsed package via {@code newPackage} in which case * Optionally, callers can pass in a parsed package via {@code scannedPackage} in which case * this function will either try and make the ABI for all packages in * {@code packagesForUser} match {@code scannedPackage} or will update the ABI of * {@code scannedPackage} to match the ABI selected for {@code packagesForUser}. This Loading @@ -76,10 +64,72 @@ interface PackageAbiHelper { * NOTE: We currently only match for the primary CPU abi string. Matching the secondary * adds unnecessary complexity. * * WARNING: This API enables modifying of the package. * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary * @return the calculated primary abi that should be set for all non-specified packages * belonging to the shared user. */ @Nullable List<String> adjustCpuAbisForSharedUser( String getAdjustedAbiForSharedUser( Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage); /** * The native library paths and related properties that should be set on a * {@link android.content.pm.PackageParser.Package}. */ final class NativeLibraryPaths { public final String nativeLibraryRootDir; public final boolean nativeLibraryRootRequiresIsa; public final String nativeLibraryDir; public final String secondaryNativeLibraryDir; @VisibleForTesting NativeLibraryPaths(String nativeLibraryRootDir, boolean nativeLibraryRootRequiresIsa, String nativeLibraryDir, String secondaryNativeLibraryDir) { this.nativeLibraryRootDir = nativeLibraryRootDir; this.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa; this.nativeLibraryDir = nativeLibraryDir; this.secondaryNativeLibraryDir = secondaryNativeLibraryDir; } public void applyTo(PackageParser.Package pkg) { pkg.applicationInfo.nativeLibraryRootDir = nativeLibraryRootDir; pkg.applicationInfo.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa; pkg.applicationInfo.nativeLibraryDir = nativeLibraryDir; pkg.applicationInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir; } } /** * The primary and secondary ABIs that should be set on a package and its package setting. */ final class Abis { public final String primary; public final String secondary; @VisibleForTesting Abis(String primary, String secondary) { this.primary = primary; this.secondary = secondary; } Abis(PackageParser.Package pkg) { this(pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi); } public void applyTo(PackageParser.Package pkg) { pkg.applicationInfo.primaryCpuAbi = primary; pkg.applicationInfo.secondaryCpuAbi = secondary; } public void applyTo(PackageSetting pkgSetting) { // pkgSetting might be null during rescan following uninstall of updates // to a bundled app, so accommodate that possibility. The settings in // that case will be established later from the parsed package. // // If the settings aren't null, sync them up with what we've derived. if (pkgSetting != null) { pkgSetting.primaryCpuAbiString = primary; pkgSetting.secondaryCpuAbiString = secondary; } } } } services/core/java/com/android/server/pm/PackageAbiHelperImpl.java +184 −198 File changed.Preview size limit exceeded, changes collapsed. Show changes services/core/java/com/android/server/pm/PackageManagerService.java +72 −10 Original line number Diff line number Diff line Loading @@ -3089,8 +3089,9 @@ public class PackageManagerService extends IPackageManager.Stub // the rest of the commands above) because there's precious little we // can do about it. A settings error is reported, though. final List<String> changedAbiCodePath = mInjector.getAbiHelper().adjustCpuAbisForSharedUser( setting.packages, null /*scannedPackage*/); applyAdjustedAbiToSharedUser(setting, null /*scannedPackage*/, mInjector.getAbiHelper().getAdjustedAbiForSharedUser( setting.packages, null /*scannedPackage*/)); if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) { for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) { final String codePathString = changedAbiCodePath.get(i); Loading Loading @@ -10663,6 +10664,50 @@ public class PackageManagerService extends IPackageManager.Stub pkg.setPackageName(renamedPackageName); } /** * Applies the adjusted ABI calculated by * {@link PackageAbiHelper#getAdjustedAbiForSharedUser(Set, PackageParser.Package)} to all * relevant packages and settings. * @param sharedUserSetting The {@code SharedUserSetting} to adjust * @param scannedPackage the package being scanned or null * @param adjustedAbi the adjusted ABI calculated by {@link PackageAbiHelper} * @return the list of code paths that belong to packages that had their ABIs adjusted. */ private static List<String> applyAdjustedAbiToSharedUser(SharedUserSetting sharedUserSetting, PackageParser.Package scannedPackage, String adjustedAbi) { if (scannedPackage != null) { scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi; } List<String> changedAbiCodePath = null; for (PackageSetting ps : sharedUserSetting.packages) { if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) { if (ps.primaryCpuAbiString != null) { continue; } ps.primaryCpuAbiString = adjustedAbi; if (ps.pkg != null && ps.pkg.applicationInfo != null && !TextUtils.equals( adjustedAbi, ps.pkg.applicationInfo.primaryCpuAbi)) { ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi; if (DEBUG_ABI_SELECTION) { Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi + " (scannedPackage=" + (scannedPackage != null ? scannedPackage : "null") + ")"); } if (changedAbiCodePath == null) { changedAbiCodePath = new ArrayList<>(); } changedAbiCodePath.add(ps.codePathString); } } } return changedAbiCodePath; } /** * Just scans the package without any side effects. * <p>Not entirely true at the moment. There is still one side effect -- this Loading Loading @@ -10835,7 +10880,10 @@ public class PackageManagerService extends IPackageManager.Stub if (needToDeriveAbi) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi"); final boolean extractNativeLibs = !pkg.isLibrary(); final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi = packageAbiHelper.derivePackageAbi(pkg, cpuAbiOverride, extractNativeLibs); derivedAbi.first.applyTo(pkg); derivedAbi.second.applyTo(pkg); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); // Some system apps still use directory structure for native libraries Loading @@ -10843,8 +10891,13 @@ public class PackageManagerService extends IPackageManager.Stub // structure. Try to detect abi based on directory structure. if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() && pkg.applicationInfo.primaryCpuAbi == null) { packageAbiHelper.setBundledAppAbisAndRoots(pkg, pkgSetting); packageAbiHelper.setNativeLibraryPaths(pkg, sAppLib32InstallDir); final PackageAbiHelper.Abis abis = packageAbiHelper.getBundledAppAbis( pkg); abis.applyTo(pkg); abis.applyTo(pkgSetting); final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = packageAbiHelper.getNativeLibraryPaths(pkg, sAppLib32InstallDir); nativeLibraryPaths.applyTo(pkg); } } else { // This is not a first boot or an upgrade, don't bother deriving the Loading @@ -10853,7 +10906,9 @@ public class PackageManagerService extends IPackageManager.Stub pkg.applicationInfo.primaryCpuAbi = primaryCpuAbiFromSettings; pkg.applicationInfo.secondaryCpuAbi = secondaryCpuAbiFromSettings; packageAbiHelper.setNativeLibraryPaths(pkg, sAppLib32InstallDir); final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = packageAbiHelper.getNativeLibraryPaths(pkg, sAppLib32InstallDir); nativeLibraryPaths.applyTo(pkg); if (DEBUG_ABI_SELECTION) { Slog.i(TAG, "Using ABIS and native lib paths from settings : " + Loading @@ -10874,7 +10929,9 @@ public class PackageManagerService extends IPackageManager.Stub // ABIs we've determined above. For non-moves, the path will be updated based on the // ABIs we determined during compilation, but the path will depend on the final // package path (after the rename away from the stage path). packageAbiHelper.setNativeLibraryPaths(pkg, sAppLib32InstallDir); final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = packageAbiHelper.getNativeLibraryPaths(pkg, sAppLib32InstallDir); nativeLibraryPaths.applyTo(pkg); } // This is a special case for the "system" package, where the ABI is Loading Loading @@ -10928,8 +10985,9 @@ public class PackageManagerService extends IPackageManager.Stub // We also do this *before* we perform dexopt on this package, so that // we can avoid redundant dexopts, and also to make sure we've got the // code and package path correct. changedAbiCodePath = packageAbiHelper.adjustCpuAbisForSharedUser( pkgSetting.sharedUser.packages, pkg); changedAbiCodePath = applyAdjustedAbiToSharedUser(pkgSetting.sharedUser, pkg, packageAbiHelper.getAdjustedAbiForSharedUser( pkgSetting.sharedUser.packages, pkg)); } if (isUnderFactoryTest && pkg.requestedPermissions.contains( Loading Loading @@ -16534,7 +16592,11 @@ public class PackageManagerService extends IPackageManager.Stub String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ? args.abiOverride : pkg.cpuAbiOverride); final boolean extractNativeLibs = !pkg.isLibrary(); mInjector.getAbiHelper().derivePackageAbi(pkg, abiOverride, extractNativeLibs); final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi = mInjector.getAbiHelper().derivePackageAbi( pkg, abiOverride, extractNativeLibs); derivedAbi.first.applyTo(pkg); derivedAbi.second.applyTo(pkg); } catch (PackageManagerException pme) { Slog.e(TAG, "Error deriving application ABI", pme); throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR, services/tests/servicestests/src/com/android/server/pm/ScanTests.java +49 −18 Original line number Diff line number Diff line Loading @@ -34,9 +34,7 @@ import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertNotSame; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.when; import android.Manifest; Loading @@ -48,6 +46,7 @@ import android.os.Environment; import android.os.UserHandle; import android.os.UserManagerInternal; import android.platform.test.annotations.Presubmit; import android.util.Pair; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; Loading @@ -62,6 +61,7 @@ import java.io.File; @RunWith(MockitoJUnitRunner.class) @Presubmit // TODO: shared user tests public class ScanTests { private static final String DUMMY_PACKAGE_NAME = "some.app.to.test"; Loading @@ -76,6 +76,24 @@ public class ScanTests { when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); } @Before public void setupDefaultAbiBehavior() throws Exception { when(mMockPackageAbiHelper.derivePackageAbi( any(PackageParser.Package.class), nullable(String.class), anyBoolean())) .thenReturn(new Pair<>( new PackageAbiHelper.Abis("derivedPrimary", "derivedSecondary"), new PackageAbiHelper.NativeLibraryPaths( "derivedRootDir", true, "derivedNativeDir", "derivedNativeDir2"))); when(mMockPackageAbiHelper.getNativeLibraryPaths( any(PackageParser.Package.class), any(File.class))) .thenReturn(new PackageAbiHelper.NativeLibraryPaths( "getRootDir", true, "getNativeDir", "getNativeDir2" )); when(mMockPackageAbiHelper.getBundledAppAbis( any(PackageParser.Package.class))) .thenReturn(new PackageAbiHelper.Abis("bundledPrimary", "bundledSecondary")); } @Test public void newInstallSimpleAllNominal() throws Exception { final PackageManagerService.ScanRequest scanRequest = Loading @@ -84,15 +102,11 @@ public class ScanTests { .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) .build(); final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/); assertThat(scanResult.existingSettingCopied, is(false)); verify(mMockPackageAbiHelper, never()).derivePackageAbi(any(PackageParser.Package.class), anyString() /*abioverride*/, anyBoolean() /*extractNativeLibs*/); verify(mMockPackageAbiHelper).setNativeLibraryPaths( scanResult.pkgSetting.pkg, PackageManagerService.sAppLib32InstallDir); assertPathsNotDerived(scanResult); } @Test Loading Loading @@ -162,10 +176,7 @@ public class ScanTests { assertThat(scanResult.pkgSetting.secondaryCpuAbiString, is("secondaryCpuAbi")); assertThat(scanResult.pkgSetting.cpuAbiOverrideString, nullValue()); verify(mMockPackageAbiHelper, never()).derivePackageAbi(any(PackageParser.Package.class), anyString() /*abioverride*/, anyBoolean() /*extractNativeLibs*/); verify(mMockPackageAbiHelper).setNativeLibraryPaths( scanResult.pkgSetting.pkg, PackageManagerService.sAppLib32InstallDir); assertPathsNotDerived(scanResult); } @Test Loading Loading @@ -293,12 +304,13 @@ public class ScanTests { .build(); executeScan(new ScanRequestBuilder(basicPackage) final PackageManagerService.ScanResult scanResult = executeScan(new ScanRequestBuilder( basicPackage) .setPkgSetting(pkgSetting) .addScanFlag(SCAN_FIRST_BOOT_OR_UPGRADE) .build()); verify(mMockPackageAbiHelper).derivePackageAbi(basicPackage, "testOverride", true); assertAbiAndPathssDerived(scanResult); } @Test Loading Loading @@ -484,7 +496,7 @@ public class ScanTests { assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting); final ApplicationInfo applicationInfo = pkgSetting.pkg.applicationInfo; verifyBasicApplicationInfo(scanResult, applicationInfo); assertBasicApplicationInfo(scanResult, applicationInfo); } Loading @@ -497,14 +509,12 @@ public class ScanTests { assertThat(pkgSetting.usesStaticLibrariesVersions, is(new long[]{234L, 456L})); assertThat(pkgSetting.pkg, is(scanResult.request.pkg)); assertThat(pkgSetting.pkg.mExtras, is(pkgSetting)); assertThat(pkgSetting.legacyNativeLibraryPathString, is("/data/tmp/randompath/base.apk:/lib")); assertThat(pkgSetting.codePath, is(new File(createCodePath(packageName)))); assertThat(pkgSetting.resourcePath, is(new File(createResourcePath(packageName)))); assertThat(pkgSetting.versionCode, is(PackageInfo.composeLongVersionCode(1, 2345))); } private static void verifyBasicApplicationInfo(PackageManagerService.ScanResult scanResult, private static void assertBasicApplicationInfo(PackageManagerService.ScanResult scanResult, ApplicationInfo applicationInfo) { assertThat(applicationInfo.processName, is(scanResult.request.pkg.packageName)); Loading @@ -517,4 +527,25 @@ public class ScanTests { assertThat(applicationInfo.credentialProtectedDataDir, is(calculatedCredentialId)); assertThat(applicationInfo.dataDir, is(applicationInfo.credentialProtectedDataDir)); } private static void assertAbiAndPathssDerived(PackageManagerService.ScanResult scanResult) { final ApplicationInfo applicationInfo = scanResult.pkgSetting.pkg.applicationInfo; assertThat(applicationInfo.primaryCpuAbi, is("derivedPrimary")); assertThat(applicationInfo.secondaryCpuAbi, is("derivedSecondary")); assertThat(applicationInfo.nativeLibraryRootDir, is("derivedRootDir")); assertThat(scanResult.pkgSetting.legacyNativeLibraryPathString, is("derivedRootDir")); assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(true)); assertThat(applicationInfo.nativeLibraryDir, is("derivedNativeDir")); assertThat(applicationInfo.secondaryNativeLibraryDir, is("derivedNativeDir2")); } private static void assertPathsNotDerived(PackageManagerService.ScanResult scanResult) { final ApplicationInfo applicationInfo = scanResult.pkgSetting.pkg.applicationInfo; assertThat(applicationInfo.nativeLibraryRootDir, is("getRootDir")); assertThat(scanResult.pkgSetting.legacyNativeLibraryPathString, is("getRootDir")); assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(true)); assertThat(applicationInfo.nativeLibraryDir, is("getNativeDir")); assertThat(applicationInfo.secondaryNativeLibraryDir, is("getNativeDir2")); } } Loading
services/core/java/com/android/server/pm/InstructionSets.java +8 −5 Original line number Diff line number Diff line Loading @@ -22,11 +22,11 @@ import android.os.SystemProperties; import android.text.TextUtils; import android.util.ArraySet; import dalvik.system.VMRuntime; import java.util.ArrayList; import java.util.List; import dalvik.system.VMRuntime; /** * Provides various methods for obtaining and converting of instruction sets. * Loading Loading @@ -113,12 +113,15 @@ public class InstructionSets { return allInstructionSets; } public static String getPrimaryInstructionSet(ApplicationInfo info) { if (info.primaryCpuAbi == null) { /** * Calculates the primary instruction set based on the computed Abis of a given package. */ public static String getPrimaryInstructionSet(PackageAbiHelper.Abis abis) { if (abis.primary == null) { return getPreferredInstructionSet(); } return VMRuntime.getInstructionSet(info.primaryCpuAbi); return VMRuntime.getInstructionSet(abis.primary); } }
services/core/java/com/android/server/pm/PackageAbiHelper.java +80 −30 Original line number Diff line number Diff line Loading @@ -18,56 +18,44 @@ package com.android.server.pm; import android.annotation.Nullable; import android.content.pm.PackageParser; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import java.io.File; import java.util.List; import java.util.Set; @VisibleForTesting interface PackageAbiHelper { /** * Derive and set the location of native libraries for the given package, * Derive and get the location of native libraries for the given package, * which varies depending on where and how the package was installed. * * WARNING: This API enables modifying of the package. * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary */ void setNativeLibraryPaths(PackageParser.Package pkg, File appLib32InstallDir); NativeLibraryPaths getNativeLibraryPaths( PackageParser.Package pkg, File appLib32InstallDir); /** * Calculate the abis and roots for a bundled app. These can uniquely * be determined from the contents of the system partition, i.e whether * it contains 64 or 32 bit shared libraries etc. We do not validate any * of this information, and instead assume that the system was built * sensibly. * * WARNING: This API enables modifying of the package. * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary * Calculate the abis for a bundled app. These can uniquely be determined from the contents of * the system partition, i.e whether it contains 64 or 32 bit shared libraries etc. We do not * validate any of this information, and instead assume that the system was built sensibly. */ void setBundledAppAbisAndRoots(PackageParser.Package pkg, PackageSetting pkgSetting); Abis getBundledAppAbis(PackageParser.Package pkg); /** * Derive the ABI of a non-system package located at {@code scanFile}. This information * is derived purely on the basis of the contents of {@code scanFile} and * {@code cpuAbiOverride}. * Derive the ABI of a non-system package located at {@code pkg}. This information * is derived purely on the basis of the contents of {@code pkg} and {@code cpuAbiOverride}. * * If {@code extractLibs} is true, native libraries are extracted from the app if required. * * WARNING: This API enables modifying of the package. * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary */ void derivePackageAbi(PackageParser.Package pkg, String cpuAbiOverride, boolean extractLibs) Pair<Abis, NativeLibraryPaths> derivePackageAbi( PackageParser.Package pkg, String cpuAbiOverride, boolean extractLibs) throws PackageManagerException; /** * Adjusts ABIs for a set of packages belonging to a shared user so that they all match. * i.e, so that all packages can be run inside a single process if required. * Calculates adjusted ABIs for a set of packages belonging to a shared user so that they all * match. i.e, so that all packages can be run inside a single process if required. * * Optionally, callers can pass in a parsed package via {@code newPackage} in which case * Optionally, callers can pass in a parsed package via {@code scannedPackage} in which case * this function will either try and make the ABI for all packages in * {@code packagesForUser} match {@code scannedPackage} or will update the ABI of * {@code scannedPackage} to match the ABI selected for {@code packagesForUser}. This Loading @@ -76,10 +64,72 @@ interface PackageAbiHelper { * NOTE: We currently only match for the primary CPU abi string. Matching the secondary * adds unnecessary complexity. * * WARNING: This API enables modifying of the package. * TODO(b/137881067): Modify so that caller is responsible for setting pkg fields as necessary * @return the calculated primary abi that should be set for all non-specified packages * belonging to the shared user. */ @Nullable List<String> adjustCpuAbisForSharedUser( String getAdjustedAbiForSharedUser( Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage); /** * The native library paths and related properties that should be set on a * {@link android.content.pm.PackageParser.Package}. */ final class NativeLibraryPaths { public final String nativeLibraryRootDir; public final boolean nativeLibraryRootRequiresIsa; public final String nativeLibraryDir; public final String secondaryNativeLibraryDir; @VisibleForTesting NativeLibraryPaths(String nativeLibraryRootDir, boolean nativeLibraryRootRequiresIsa, String nativeLibraryDir, String secondaryNativeLibraryDir) { this.nativeLibraryRootDir = nativeLibraryRootDir; this.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa; this.nativeLibraryDir = nativeLibraryDir; this.secondaryNativeLibraryDir = secondaryNativeLibraryDir; } public void applyTo(PackageParser.Package pkg) { pkg.applicationInfo.nativeLibraryRootDir = nativeLibraryRootDir; pkg.applicationInfo.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa; pkg.applicationInfo.nativeLibraryDir = nativeLibraryDir; pkg.applicationInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir; } } /** * The primary and secondary ABIs that should be set on a package and its package setting. */ final class Abis { public final String primary; public final String secondary; @VisibleForTesting Abis(String primary, String secondary) { this.primary = primary; this.secondary = secondary; } Abis(PackageParser.Package pkg) { this(pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi); } public void applyTo(PackageParser.Package pkg) { pkg.applicationInfo.primaryCpuAbi = primary; pkg.applicationInfo.secondaryCpuAbi = secondary; } public void applyTo(PackageSetting pkgSetting) { // pkgSetting might be null during rescan following uninstall of updates // to a bundled app, so accommodate that possibility. The settings in // that case will be established later from the parsed package. // // If the settings aren't null, sync them up with what we've derived. if (pkgSetting != null) { pkgSetting.primaryCpuAbiString = primary; pkgSetting.secondaryCpuAbiString = secondary; } } } }
services/core/java/com/android/server/pm/PackageAbiHelperImpl.java +184 −198 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/core/java/com/android/server/pm/PackageManagerService.java +72 −10 Original line number Diff line number Diff line Loading @@ -3089,8 +3089,9 @@ public class PackageManagerService extends IPackageManager.Stub // the rest of the commands above) because there's precious little we // can do about it. A settings error is reported, though. final List<String> changedAbiCodePath = mInjector.getAbiHelper().adjustCpuAbisForSharedUser( setting.packages, null /*scannedPackage*/); applyAdjustedAbiToSharedUser(setting, null /*scannedPackage*/, mInjector.getAbiHelper().getAdjustedAbiForSharedUser( setting.packages, null /*scannedPackage*/)); if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) { for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) { final String codePathString = changedAbiCodePath.get(i); Loading Loading @@ -10663,6 +10664,50 @@ public class PackageManagerService extends IPackageManager.Stub pkg.setPackageName(renamedPackageName); } /** * Applies the adjusted ABI calculated by * {@link PackageAbiHelper#getAdjustedAbiForSharedUser(Set, PackageParser.Package)} to all * relevant packages and settings. * @param sharedUserSetting The {@code SharedUserSetting} to adjust * @param scannedPackage the package being scanned or null * @param adjustedAbi the adjusted ABI calculated by {@link PackageAbiHelper} * @return the list of code paths that belong to packages that had their ABIs adjusted. */ private static List<String> applyAdjustedAbiToSharedUser(SharedUserSetting sharedUserSetting, PackageParser.Package scannedPackage, String adjustedAbi) { if (scannedPackage != null) { scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi; } List<String> changedAbiCodePath = null; for (PackageSetting ps : sharedUserSetting.packages) { if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) { if (ps.primaryCpuAbiString != null) { continue; } ps.primaryCpuAbiString = adjustedAbi; if (ps.pkg != null && ps.pkg.applicationInfo != null && !TextUtils.equals( adjustedAbi, ps.pkg.applicationInfo.primaryCpuAbi)) { ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi; if (DEBUG_ABI_SELECTION) { Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi + " (scannedPackage=" + (scannedPackage != null ? scannedPackage : "null") + ")"); } if (changedAbiCodePath == null) { changedAbiCodePath = new ArrayList<>(); } changedAbiCodePath.add(ps.codePathString); } } } return changedAbiCodePath; } /** * Just scans the package without any side effects. * <p>Not entirely true at the moment. There is still one side effect -- this Loading Loading @@ -10835,7 +10880,10 @@ public class PackageManagerService extends IPackageManager.Stub if (needToDeriveAbi) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi"); final boolean extractNativeLibs = !pkg.isLibrary(); final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi = packageAbiHelper.derivePackageAbi(pkg, cpuAbiOverride, extractNativeLibs); derivedAbi.first.applyTo(pkg); derivedAbi.second.applyTo(pkg); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); // Some system apps still use directory structure for native libraries Loading @@ -10843,8 +10891,13 @@ public class PackageManagerService extends IPackageManager.Stub // structure. Try to detect abi based on directory structure. if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() && pkg.applicationInfo.primaryCpuAbi == null) { packageAbiHelper.setBundledAppAbisAndRoots(pkg, pkgSetting); packageAbiHelper.setNativeLibraryPaths(pkg, sAppLib32InstallDir); final PackageAbiHelper.Abis abis = packageAbiHelper.getBundledAppAbis( pkg); abis.applyTo(pkg); abis.applyTo(pkgSetting); final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = packageAbiHelper.getNativeLibraryPaths(pkg, sAppLib32InstallDir); nativeLibraryPaths.applyTo(pkg); } } else { // This is not a first boot or an upgrade, don't bother deriving the Loading @@ -10853,7 +10906,9 @@ public class PackageManagerService extends IPackageManager.Stub pkg.applicationInfo.primaryCpuAbi = primaryCpuAbiFromSettings; pkg.applicationInfo.secondaryCpuAbi = secondaryCpuAbiFromSettings; packageAbiHelper.setNativeLibraryPaths(pkg, sAppLib32InstallDir); final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = packageAbiHelper.getNativeLibraryPaths(pkg, sAppLib32InstallDir); nativeLibraryPaths.applyTo(pkg); if (DEBUG_ABI_SELECTION) { Slog.i(TAG, "Using ABIS and native lib paths from settings : " + Loading @@ -10874,7 +10929,9 @@ public class PackageManagerService extends IPackageManager.Stub // ABIs we've determined above. For non-moves, the path will be updated based on the // ABIs we determined during compilation, but the path will depend on the final // package path (after the rename away from the stage path). packageAbiHelper.setNativeLibraryPaths(pkg, sAppLib32InstallDir); final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = packageAbiHelper.getNativeLibraryPaths(pkg, sAppLib32InstallDir); nativeLibraryPaths.applyTo(pkg); } // This is a special case for the "system" package, where the ABI is Loading Loading @@ -10928,8 +10985,9 @@ public class PackageManagerService extends IPackageManager.Stub // We also do this *before* we perform dexopt on this package, so that // we can avoid redundant dexopts, and also to make sure we've got the // code and package path correct. changedAbiCodePath = packageAbiHelper.adjustCpuAbisForSharedUser( pkgSetting.sharedUser.packages, pkg); changedAbiCodePath = applyAdjustedAbiToSharedUser(pkgSetting.sharedUser, pkg, packageAbiHelper.getAdjustedAbiForSharedUser( pkgSetting.sharedUser.packages, pkg)); } if (isUnderFactoryTest && pkg.requestedPermissions.contains( Loading Loading @@ -16534,7 +16592,11 @@ public class PackageManagerService extends IPackageManager.Stub String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ? args.abiOverride : pkg.cpuAbiOverride); final boolean extractNativeLibs = !pkg.isLibrary(); mInjector.getAbiHelper().derivePackageAbi(pkg, abiOverride, extractNativeLibs); final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi = mInjector.getAbiHelper().derivePackageAbi( pkg, abiOverride, extractNativeLibs); derivedAbi.first.applyTo(pkg); derivedAbi.second.applyTo(pkg); } catch (PackageManagerException pme) { Slog.e(TAG, "Error deriving application ABI", pme); throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
services/tests/servicestests/src/com/android/server/pm/ScanTests.java +49 −18 Original line number Diff line number Diff line Loading @@ -34,9 +34,7 @@ import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertNotSame; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.when; import android.Manifest; Loading @@ -48,6 +46,7 @@ import android.os.Environment; import android.os.UserHandle; import android.os.UserManagerInternal; import android.platform.test.annotations.Presubmit; import android.util.Pair; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; Loading @@ -62,6 +61,7 @@ import java.io.File; @RunWith(MockitoJUnitRunner.class) @Presubmit // TODO: shared user tests public class ScanTests { private static final String DUMMY_PACKAGE_NAME = "some.app.to.test"; Loading @@ -76,6 +76,24 @@ public class ScanTests { when(mMockUserManager.getUserIds()).thenReturn(new int[]{0}); } @Before public void setupDefaultAbiBehavior() throws Exception { when(mMockPackageAbiHelper.derivePackageAbi( any(PackageParser.Package.class), nullable(String.class), anyBoolean())) .thenReturn(new Pair<>( new PackageAbiHelper.Abis("derivedPrimary", "derivedSecondary"), new PackageAbiHelper.NativeLibraryPaths( "derivedRootDir", true, "derivedNativeDir", "derivedNativeDir2"))); when(mMockPackageAbiHelper.getNativeLibraryPaths( any(PackageParser.Package.class), any(File.class))) .thenReturn(new PackageAbiHelper.NativeLibraryPaths( "getRootDir", true, "getNativeDir", "getNativeDir2" )); when(mMockPackageAbiHelper.getBundledAppAbis( any(PackageParser.Package.class))) .thenReturn(new PackageAbiHelper.Abis("bundledPrimary", "bundledSecondary")); } @Test public void newInstallSimpleAllNominal() throws Exception { final PackageManagerService.ScanRequest scanRequest = Loading @@ -84,15 +102,11 @@ public class ScanTests { .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) .build(); final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/); assertThat(scanResult.existingSettingCopied, is(false)); verify(mMockPackageAbiHelper, never()).derivePackageAbi(any(PackageParser.Package.class), anyString() /*abioverride*/, anyBoolean() /*extractNativeLibs*/); verify(mMockPackageAbiHelper).setNativeLibraryPaths( scanResult.pkgSetting.pkg, PackageManagerService.sAppLib32InstallDir); assertPathsNotDerived(scanResult); } @Test Loading Loading @@ -162,10 +176,7 @@ public class ScanTests { assertThat(scanResult.pkgSetting.secondaryCpuAbiString, is("secondaryCpuAbi")); assertThat(scanResult.pkgSetting.cpuAbiOverrideString, nullValue()); verify(mMockPackageAbiHelper, never()).derivePackageAbi(any(PackageParser.Package.class), anyString() /*abioverride*/, anyBoolean() /*extractNativeLibs*/); verify(mMockPackageAbiHelper).setNativeLibraryPaths( scanResult.pkgSetting.pkg, PackageManagerService.sAppLib32InstallDir); assertPathsNotDerived(scanResult); } @Test Loading Loading @@ -293,12 +304,13 @@ public class ScanTests { .build(); executeScan(new ScanRequestBuilder(basicPackage) final PackageManagerService.ScanResult scanResult = executeScan(new ScanRequestBuilder( basicPackage) .setPkgSetting(pkgSetting) .addScanFlag(SCAN_FIRST_BOOT_OR_UPGRADE) .build()); verify(mMockPackageAbiHelper).derivePackageAbi(basicPackage, "testOverride", true); assertAbiAndPathssDerived(scanResult); } @Test Loading Loading @@ -484,7 +496,7 @@ public class ScanTests { assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting); final ApplicationInfo applicationInfo = pkgSetting.pkg.applicationInfo; verifyBasicApplicationInfo(scanResult, applicationInfo); assertBasicApplicationInfo(scanResult, applicationInfo); } Loading @@ -497,14 +509,12 @@ public class ScanTests { assertThat(pkgSetting.usesStaticLibrariesVersions, is(new long[]{234L, 456L})); assertThat(pkgSetting.pkg, is(scanResult.request.pkg)); assertThat(pkgSetting.pkg.mExtras, is(pkgSetting)); assertThat(pkgSetting.legacyNativeLibraryPathString, is("/data/tmp/randompath/base.apk:/lib")); assertThat(pkgSetting.codePath, is(new File(createCodePath(packageName)))); assertThat(pkgSetting.resourcePath, is(new File(createResourcePath(packageName)))); assertThat(pkgSetting.versionCode, is(PackageInfo.composeLongVersionCode(1, 2345))); } private static void verifyBasicApplicationInfo(PackageManagerService.ScanResult scanResult, private static void assertBasicApplicationInfo(PackageManagerService.ScanResult scanResult, ApplicationInfo applicationInfo) { assertThat(applicationInfo.processName, is(scanResult.request.pkg.packageName)); Loading @@ -517,4 +527,25 @@ public class ScanTests { assertThat(applicationInfo.credentialProtectedDataDir, is(calculatedCredentialId)); assertThat(applicationInfo.dataDir, is(applicationInfo.credentialProtectedDataDir)); } private static void assertAbiAndPathssDerived(PackageManagerService.ScanResult scanResult) { final ApplicationInfo applicationInfo = scanResult.pkgSetting.pkg.applicationInfo; assertThat(applicationInfo.primaryCpuAbi, is("derivedPrimary")); assertThat(applicationInfo.secondaryCpuAbi, is("derivedSecondary")); assertThat(applicationInfo.nativeLibraryRootDir, is("derivedRootDir")); assertThat(scanResult.pkgSetting.legacyNativeLibraryPathString, is("derivedRootDir")); assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(true)); assertThat(applicationInfo.nativeLibraryDir, is("derivedNativeDir")); assertThat(applicationInfo.secondaryNativeLibraryDir, is("derivedNativeDir2")); } private static void assertPathsNotDerived(PackageManagerService.ScanResult scanResult) { final ApplicationInfo applicationInfo = scanResult.pkgSetting.pkg.applicationInfo; assertThat(applicationInfo.nativeLibraryRootDir, is("getRootDir")); assertThat(scanResult.pkgSetting.legacyNativeLibraryPathString, is("getRootDir")); assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(true)); assertThat(applicationInfo.nativeLibraryDir, is("getNativeDir")); assertThat(applicationInfo.secondaryNativeLibraryDir, is("getNativeDir2")); } }