Merge "[pm] Skip parsing abis from the apex file in scan flow" into main

This commit is contained in:
Ivan Chiang
2023-07-17 05:30:11 +00:00
committed by Android (Google) Code Review
3 changed files with 139 additions and 84 deletions

View File

@@ -1509,29 +1509,34 @@ final class InstallPackageHelper {
} else {
// Enable SCAN_NO_DEX flag to skip dexopt at a later stage
scanFlags |= SCAN_NO_DEX;
// The native libs of Apex is located in apex_payload.img, don't need to parse it from
// the original apex file
if (!isApex) {
try {
PackageSetting pkgSetting;
synchronized (mPm.mLock) {
pkgSetting = mPm.mSettings.getPackageLPr(pkgName);
}
boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null
&& pkgSetting.isUpdatedSystemApp();
final String abiOverride = deriveAbiOverride(request.getAbiOverride());
try {
PackageSetting pkgSetting;
synchronized (mPm.mLock) {
pkgSetting = mPm.mSettings.getPackageLPr(pkgName);
// TODO: Are these system flags actually set properly at this stage?
boolean isUpdatedSystemAppInferred =
pkgSetting != null && pkgSetting.isSystem();
final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
derivedAbi = mPackageAbiHelper.derivePackageAbi(parsedPackage,
systemApp, (isUpdatedSystemAppFromExistingSetting
|| isUpdatedSystemAppInferred), abiOverride,
ScanPackageUtils.getAppLib32InstallDir());
derivedAbi.first.applyTo(parsedPackage);
derivedAbi.second.applyTo(parsedPackage);
} catch (PackageManagerException pme) {
Slog.e(TAG, "Error deriving application ABI", pme);
throw PrepareFailure.ofInternalError(
"Error deriving application ABI: " + pme.getMessage(),
PackageManagerException.INTERNAL_ERROR_DERIVING_ABI);
}
boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null
&& pkgSetting.isUpdatedSystemApp();
final String abiOverride = deriveAbiOverride(request.getAbiOverride());
// TODO: Are these system flags actually set properly at this stage?
boolean isUpdatedSystemAppInferred = pkgSetting != null && pkgSetting.isSystem();
final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
derivedAbi = mPackageAbiHelper.derivePackageAbi(parsedPackage, systemApp,
isUpdatedSystemAppFromExistingSetting || isUpdatedSystemAppInferred,
abiOverride, ScanPackageUtils.getAppLib32InstallDir());
derivedAbi.first.applyTo(parsedPackage);
derivedAbi.second.applyTo(parsedPackage);
} catch (PackageManagerException pme) {
Slog.e(TAG, "Error deriving application ABI", pme);
throw PrepareFailure.ofInternalError(
"Error deriving application ABI: " + pme.getMessage(),
PackageManagerException.INTERNAL_ERROR_DERIVING_ABI);
}
}

View File

@@ -149,6 +149,8 @@ final class ScanPackageUtils {
String primaryCpuAbiFromSettings = null;
String secondaryCpuAbiFromSettings = null;
boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0;
boolean isApex = (scanFlags & SCAN_AS_APEX) != 0;
if (!needToDeriveAbi) {
if (pkgSetting != null) {
// TODO(b/154610922): if it is not first boot or upgrade, we should directly use
@@ -240,6 +242,7 @@ final class ScanPackageUtils {
usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(),
parsedPackage.getMimeGroups(), newDomainSetId);
}
if (createNewPackage && originalPkgSetting != null) {
// This is the initial transition from the original package, so,
// fix up the new package's name now. We must do this after looking
@@ -279,85 +282,91 @@ final class ScanPackageUtils {
final boolean isUpdatedSystemApp = pkgSetting.isUpdatedSystemApp();
final File appLib32InstallDir = getAppLib32InstallDir();
if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
if (needToDeriveAbi) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
try {
final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
derivedAbi =
packageAbiHelper.derivePackageAbi(
parsedPackage,
isSystemApp,
isUpdatedSystemApp,
cpuAbiOverride,
appLib32InstallDir);
derivedAbi.first.applyTo(parsedPackage);
derivedAbi.second.applyTo(parsedPackage);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
// The native libs of Apex is located in apex_payload.img, don't need to parse it from
// the original apex file
if (!isApex) {
if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
if (needToDeriveAbi) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
try {
final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
derivedAbi =
packageAbiHelper.derivePackageAbi(
parsedPackage,
isSystemApp,
isUpdatedSystemApp,
cpuAbiOverride,
appLib32InstallDir);
derivedAbi.first.applyTo(parsedPackage);
derivedAbi.second.applyTo(parsedPackage);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
// Some system apps still use directory structure for native libraries
// in which case we might end up not detecting abi solely based on apk
// structure. Try to detect abi based on directory structure.
// Some system apps still use directory structure for native libraries
// in which case we might end up not detecting abi solely based on apk
// structure. Try to detect abi based on directory structure.
String pkgRawPrimaryCpuAbi = AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage);
if (isSystemApp && !isUpdatedSystemApp && pkgRawPrimaryCpuAbi == null) {
final PackageAbiHelper.Abis abis = packageAbiHelper.getBundledAppAbis(
String pkgRawPrimaryCpuAbi = AndroidPackageUtils.getRawPrimaryCpuAbi(
parsedPackage);
abis.applyTo(parsedPackage);
abis.applyTo(pkgSetting);
if (isSystemApp && !isUpdatedSystemApp && pkgRawPrimaryCpuAbi == null) {
final PackageAbiHelper.Abis abis = packageAbiHelper.getBundledAppAbis(
parsedPackage);
abis.applyTo(parsedPackage);
abis.applyTo(pkgSetting);
final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
packageAbiHelper.deriveNativeLibraryPaths(parsedPackage,
isSystemApp, isUpdatedSystemApp, appLib32InstallDir);
nativeLibraryPaths.applyTo(parsedPackage);
}
} else {
// This is not a first boot or an upgrade, don't bother deriving the
// ABI during the scan. Instead, trust the value that was stored in the
// package setting.
parsedPackage.setPrimaryCpuAbi(primaryCpuAbiFromSettings)
.setSecondaryCpuAbi(secondaryCpuAbiFromSettings);
final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, isSystemApp,
isUpdatedSystemApp, appLib32InstallDir);
nativeLibraryPaths.applyTo(parsedPackage);
if (DEBUG_ABI_SELECTION) {
Slog.i(TAG, "Using ABIS and native lib paths from settings : "
+ parsedPackage.getPackageName() + " "
+ AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage)
+ ", "
+ AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage));
}
}
} else {
// This is not a first boot or an upgrade, don't bother deriving the
// ABI during the scan. Instead, trust the value that was stored in the
// package setting.
parsedPackage.setPrimaryCpuAbi(primaryCpuAbiFromSettings)
.setSecondaryCpuAbi(secondaryCpuAbiFromSettings);
if ((scanFlags & SCAN_MOVE) != 0) {
// We haven't run dex-opt for this move (since we've moved the compiled output
// too) but we already have this packages package info in the PackageSetting.
// We just use that and derive the native library path based on the new code
// path.
parsedPackage.setPrimaryCpuAbi(pkgSetting.getPrimaryCpuAbiLegacy())
.setSecondaryCpuAbi(pkgSetting.getSecondaryCpuAbiLegacy());
}
// Set native library paths again. For moves, the path will be updated based on the
// 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).
final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, isSystemApp,
isUpdatedSystemApp, appLib32InstallDir);
nativeLibraryPaths.applyTo(parsedPackage);
if (DEBUG_ABI_SELECTION) {
Slog.i(TAG, "Using ABIS and native lib paths from settings : "
+ parsedPackage.getPackageName() + " "
+ AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage)
+ ", "
+ AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage));
}
}
} else {
if ((scanFlags & SCAN_MOVE) != 0) {
// We haven't run dex-opt for this move (since we've moved the compiled output too)
// but we already have this packages package info in the PackageSetting. We just
// use that and derive the native library path based on the new code path.
parsedPackage.setPrimaryCpuAbi(pkgSetting.getPrimaryCpuAbiLegacy())
.setSecondaryCpuAbi(pkgSetting.getSecondaryCpuAbiLegacy());
}
// Set native library paths again. For moves, the path will be updated based on the
// 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).
final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, isSystemApp,
isUpdatedSystemApp, appLib32InstallDir);
nativeLibraryPaths.applyTo(parsedPackage);
}
// This is a special case for the "system" package, where the ABI is
// dictated by the zygote configuration (and init.rc). We should keep track
// of this ABI so that we can deal with "normal" applications that run under
// the same UID correctly.
if (isPlatformPackage) {
parsedPackage.setPrimaryCpuAbi(VMRuntime.getRuntime().is64Bit()
? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]);
// This is a special case for the "system" package, where the ABI is
// dictated by the zygote configuration (and init.rc). We should keep track
// of this ABI so that we can deal with "normal" applications that run under
// the same UID correctly.
if (isPlatformPackage) {
parsedPackage.setPrimaryCpuAbi(VMRuntime.getRuntime().is64Bit()
? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]);
}
}
// If there's a mismatch between the abi-override in the package setting

View File

@@ -21,6 +21,7 @@ import static android.content.pm.SharedLibraryInfo.TYPE_SDK_PACKAGE;
import static android.content.pm.SharedLibraryInfo.TYPE_STATIC;
import static android.content.pm.SharedLibraryInfo.VERSION_UNDEFINED;
import static com.android.server.pm.PackageManagerService.SCAN_AS_APEX;
import static com.android.server.pm.PackageManagerService.SCAN_AS_FULL_APP;
import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP;
import static com.android.server.pm.PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE;
@@ -364,6 +365,46 @@ public class ScanTests {
assertThat(scanResult.mPkgSetting.getVolumeUuid(), is(UUID_TWO.toString()));
}
@Test
public void scanFirstBoot_apexDontDeriveAbis() throws Exception {
final PackageSetting pkgSetting =
createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME)
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM).build();
final String codePath = "/data/apex/" + DUMMY_PACKAGE_NAME + ".apex";
// Create the ParsedPackage for the apex
final ParsedPackage basicPackage =
((ParsedPackage) new PackageImpl(DUMMY_PACKAGE_NAME, codePath, codePath,
mock(TypedArray.class), false)
.setVolumeUuid(UUID_ONE.toString())
.hideAsParsed())
.setVersionCodeMajor(1)
.setVersionCode(2345)
.setSystem(true);
when(mMockInjector.getAbiHelper()).thenReturn(new PackageAbiHelperImpl());
// prepare the scan request with the scanflag (SCAN_FIRST_BOOT_OR_UPGRADE | SCAN_AS_APEX)
final ScanResult scanResult = executeScan(new ScanRequestBuilder(basicPackage)
.setPkgSetting(pkgSetting)
.addScanFlag(SCAN_FIRST_BOOT_OR_UPGRADE | SCAN_AS_APEX)
.build());
final PackageSetting resultSetting = scanResult.mPkgSetting;
final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo(
resultSetting.getPkg(), 0, pkgSetting.getUserStateOrDefault(0), 0, resultSetting);
assertThat(applicationInfo.primaryCpuAbi, nullValue());
assertThat(applicationInfo.primaryCpuAbi, nullValue());
assertThat(applicationInfo.secondaryCpuAbi, nullValue());
assertThat(applicationInfo.nativeLibraryRootDir, nullValue());
assertThat(pkgSetting.getLegacyNativeLibraryPath(), nullValue());
assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(false));
assertThat(applicationInfo.nativeLibraryDir, nullValue());
assertThat(applicationInfo.secondaryNativeLibraryDir, nullValue());
}
@Test
public void scanFirstBoot_derivesAbis() throws Exception {
final PackageSetting pkgSetting =