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

Commit 0a0559c0 authored by Alan Stokes's avatar Alan Stokes Committed by android-build-merger
Browse files

Merge "DexLoadReporter needs to handle arbitrary class loaders." am: f2d5ace0

am: 1e292647

Change-Id: I41caab25c48d496722ac4d044908dd781df1705d
parents 9c10dcc0 1e292647
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ import java.util.Set;
    }

    @Override
    public void report(List<BaseDexClassLoader> classLoadersChain, List<String> classPaths) {
    public void report(List<ClassLoader> classLoadersChain, List<String> classPaths) {
        if (classLoadersChain.size() != classPaths.size()) {
            Slog.wtf(TAG, "Bad call to DexLoadReporter: argument size mismatch");
            return;
@@ -113,12 +113,12 @@ import java.util.Set;
        registerSecondaryDexForProfiling(dexPathsForRegistration);
    }

    private void notifyPackageManager(List<BaseDexClassLoader> classLoadersChain,
    private void notifyPackageManager(List<ClassLoader> classLoadersChain,
            List<String> classPaths) {
        // Get the class loader names for the binder call.
        List<String> classLoadersNames = new ArrayList<>(classPaths.size());
        for (BaseDexClassLoader bdc : classLoadersChain) {
            classLoadersNames.add(bdc.getClass().getName());
        for (ClassLoader classLoader : classLoadersChain) {
            classLoadersNames.add(classLoader.getClass().getName());
        }
        String packageName = ActivityThread.currentPackageName();
        try {
+1 −1
Original line number Diff line number Diff line
@@ -475,7 +475,7 @@ interface IPackageManager {
     * @param classPaths the class paths corresponding to the class loaders names from
     *     {@param classLoadersNames}. The the first element corresponds to the first class loader
     *     and so on. A classpath is represented as a list of dex files separated by
     *     {@code File.pathSeparator}.
     *     {@code File.pathSeparator}, or null if the class loader's classpath is not known.
     *     The dex files found in the first class path will be recorded in the usage file.
     * @param loaderIsa the ISA of the loader process
     */
+11 −3
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.util.Slog;
import android.util.jar.StrictJarFile;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.server.pm.Installer;
import com.android.server.pm.Installer.InstallerException;
@@ -153,7 +154,7 @@ public class DexManager {
     * @param classPaths the class paths corresponding to the class loaders names from
     *     {@param classLoadersNames}. The the first element corresponds to the first class loader
     *     and so on. A classpath is represented as a list of dex files separated by
     *     {@code File.pathSeparator}.
     *     {@code File.pathSeparator}, or null if the class loader's classpath is not known.
     *     The dex files found in the first class path will be recorded in the usage file.
     * @param loaderIsa the ISA of the app loading the dex files
     * @param loaderUserId the user id which runs the code loading the dex files
@@ -169,7 +170,8 @@ public class DexManager {
        }
    }

    private void notifyDexLoadInternal(ApplicationInfo loadingAppInfo,
    @VisibleForTesting
    /*package*/ void notifyDexLoadInternal(ApplicationInfo loadingAppInfo,
            List<String> classLoaderNames, List<String> classPaths, String loaderIsa,
            int loaderUserId) {
        if (classLoaderNames.size() != classPaths.size()) {
@@ -186,8 +188,14 @@ public class DexManager {
            return;
        }

        // The first classpath should never be null because the first classloader
        // should always be an instance of BaseDexClassLoader.
        String firstClassPath = classPaths.get(0);
        if (firstClassPath == null) {
            return;
        }
        // The classpath is represented as a list of dex files separated by File.pathSeparator.
        String[] dexPathsToRegister = classPaths.get(0).split(File.pathSeparator);
        String[] dexPathsToRegister = firstClassPath.split(File.pathSeparator);

        // Encode the class loader contexts for the dexPathsToRegister.
        String[] classLoaderContexts = DexoptUtils.processContextForDexLoad(
+2 −1
Original line number Diff line number Diff line
@@ -318,7 +318,8 @@ public final class DexoptUtils {
        // is fine (they come over binder). Even if something changes we expect the sizes to be
        // very small and it shouldn't matter much.
        for (int i = 1; i < classLoadersNames.size(); i++) {
            if (!ClassLoaderFactory.isValidClassLoaderName(classLoadersNames.get(i))) {
            if (!ClassLoaderFactory.isValidClassLoaderName(classLoadersNames.get(i))
                || classPaths.get(i) == null) {
                return null;
            }
            String classpath = encodeClasspath(classPaths.get(i).split(File.pathSeparator));
+28 −6
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ public class DexManagerTests {
    private static final String PATH_CLASS_LOADER_NAME = PathClassLoader.class.getName();
    private static final String DELEGATE_LAST_CLASS_LOADER_NAME =
            DelegateLastClassLoader.class.getName();
    private static final String UNSUPPORTED_CLASS_LOADER_NAME = "unsupported.class_loader";

    @Rule public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
    @Mock Installer mInstaller;
@@ -106,7 +107,7 @@ public class DexManagerTests {
        mDoesNotExist = new TestData("DOES.NOT.EXIST", isa, mUser1);

        mBarUser0UnsupportedClassLoader = new TestData(bar, isa, mUser0,
                "unsupported.class_loader");
                UNSUPPORTED_CLASS_LOADER_NAME);
        mBarUser0DelegateLastClassLoader = new TestData(bar, isa, mUser0,
                DELEGATE_LAST_CLASS_LOADER_NAME);

@@ -405,6 +406,24 @@ public class DexManagerTests {
        assertNoUseInfo(mBarUser0UnsupportedClassLoader);
    }

    @Test
    public void testNotifySupportedAndUnsupportedClassLoader() {
        String classPath = String.join(File.pathSeparator, mBarUser0.getSecondaryDexPaths());
        List<String> classLoaders =
                Arrays.asList(PATH_CLASS_LOADER_NAME, UNSUPPORTED_CLASS_LOADER_NAME);
        List<String> classPaths = Arrays.asList(classPath, classPath);
        notifyDexLoad(mBarUser0, classLoaders, classPaths, mUser0);

        assertNoUseInfo(mBarUser0);
    }

    @Test
    public void testNotifyNullClassPath() {
        notifyDexLoad(mBarUser0, null, mUser0);

        assertNoUseInfo(mBarUser0);
    }

    @Test
    public void testNotifyVariableClassLoader() {
        // Record bar secondaries with the default PathClassLoader.
@@ -500,14 +519,17 @@ public class DexManagerTests {
        // By default, assume a single class loader in the chain.
        // This makes writing tests much easier.
        List<String> classLoaders = Arrays.asList(testData.mClassLoader);
        List<String> classPaths = Arrays.asList(String.join(File.pathSeparator, dexPaths));
        List<String> classPaths = (dexPaths == null)
                                  ? Arrays.asList((String) null)
                                  : Arrays.asList(String.join(File.pathSeparator, dexPaths));
        notifyDexLoad(testData, classLoaders, classPaths, loaderUserId);
    }

    private void notifyDexLoad(TestData testData, List<String> classLoader, List<String> classPaths,
            int loaderUserId) {
        mDexManager.notifyDexLoad(testData.mPackageInfo.applicationInfo, classLoader, classPaths,
                testData.mLoaderIsa, loaderUserId);
    private void notifyDexLoad(TestData testData, List<String> classLoaders,
            List<String> classPaths, int loaderUserId) {
        // We call the internal function so any exceptions thrown cause test failures.
        mDexManager.notifyDexLoadInternal(testData.mPackageInfo.applicationInfo, classLoaders,
                classPaths, testData.mLoaderIsa, loaderUserId);
    }

    private PackageUseInfo getPackageUseInfo(TestData testData) {
Loading