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

Commit c7487391 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "PackageAbiHepler no longer modifies Package"

parents bbdfc57b 745f948e
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -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.
 *
@@ -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);
    }

}
+80 −30
Original line number Diff line number Diff line
@@ -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
@@ -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;
            }
        }
    }
}
+184 −198

File changed.

Preview size limit exceeded, changes collapsed.

+72 −10
Original line number Diff line number Diff line
@@ -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);
@@ -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
@@ -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
@@ -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
@@ -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 : " +
@@ -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
@@ -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(
@@ -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,
+49 −18
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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";
@@ -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 =
@@ -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
@@ -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
@@ -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
@@ -484,7 +496,7 @@ public class ScanTests {
        assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting);

        final ApplicationInfo applicationInfo = pkgSetting.pkg.applicationInfo;
        verifyBasicApplicationInfo(scanResult, applicationInfo);
        assertBasicApplicationInfo(scanResult, applicationInfo);

    }

@@ -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));

@@ -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"));
    }
}