[pm] Skip parsing abis from the apex file in scan flow

From U, We merged the APK and APEX scan flows so that they run the
same code branch, rather than having ApexManager maintain a separate
parsing implementation. For parsing the abis in scan flow, because
the native libs of an Apex is located in apex_payload.img, don't need
to parse it from the original apex file when scanning the apex file.

Test: atest ScanTests#scanFirstBoot_apexDontDeriveAbis
          --iterations 100
Test: atest ScanTests --iterations 100
Test: Manual. run atest BootTest, verified the logs
Bug: 288167712
Change-Id: I3bd0d8250fd27e1aff2a16bef1495f1c9cfba472
This commit is contained in:
Ivan Chiang
2023-07-14 09:35:57 +00:00
parent 15d68f4163
commit 772c11783c
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 =