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

Commit 7f920c22 authored by Adam Lesinski's avatar Adam Lesinski Committed by Android Git Automerger
Browse files

am 7f3b7116: Merge "Shared library resource support"

* commit '7f3b7116':
  Shared library resource support
parents 70054d15 7f3b7116
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -119,7 +119,8 @@ namespace {

    int parse_manifest(const void *data, size_t size, const char *target_package_name)
    {
        ResXMLTree parser(data, size);
        ResXMLTree parser;
        parser.setTo(data, size);
        if (parser.getError() != NO_ERROR) {
            ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError());
            return -1;
+2 −2
Original line number Diff line number Diff line
@@ -1592,10 +1592,10 @@ public final class ActivityThread {
    /**
     * Creates the top level resources for the given package.
     */
    Resources getTopLevelResources(String resDir, String[] overlayDirs,
    Resources getTopLevelResources(String resDir, String[] overlayDirs, String[] libDirs,
            int displayId, Configuration overrideConfiguration,
            LoadedApk pkgInfo) {
        return mResourcesManager.getTopLevelResources(resDir, overlayDirs, displayId,
        return mResourcesManager.getTopLevelResources(resDir, overlayDirs, libDirs, displayId,
                overrideConfiguration, pkgInfo.getCompatibilityInfo(), null);
    }

+1 −1
Original line number Diff line number Diff line
@@ -805,7 +805,7 @@ final class ApplicationPackageManager extends PackageManager {
        }
        Resources r = mContext.mMainThread.getTopLevelResources(
                app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir,
                app.resourceDirs, Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo);
                app.resourceDirs, null, Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo);
        if (r != null) {
            return r;
        }
+3 −2
Original line number Diff line number Diff line
@@ -2044,8 +2044,9 @@ class ContextImpl extends Context {
                    || (compatInfo != null && compatInfo.applicationScale
                            != resources.getCompatibilityInfo().applicationScale)) {
                resources = mResourcesManager.getTopLevelResources(
                        packageInfo.getResDir(), packageInfo.getOverlayDirs(), displayId,
                        overrideConfiguration, compatInfo, activityToken);
                        packageInfo.getResDir(), packageInfo.getOverlayDirs(),
                        packageInfo.getApplicationInfo().sharedLibraryFiles,
                        displayId, overrideConfiguration, compatInfo, activityToken);
            }
        }
        mResources = resources;
+96 −2
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.util.AndroidRuntimeException;
import android.util.Slog;
import android.util.SparseArray;
import android.view.DisplayAdjustments;
import android.view.Display;

@@ -48,6 +49,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Enumeration;

@@ -485,7 +488,7 @@ public final class LoadedApk {
    public Resources getResources(ActivityThread mainThread) {
        if (mResources == null) {
            mResources = mainThread.getTopLevelResources(mResDir, mOverlayDirs,
                    Display.DEFAULT_DISPLAY, null, this);
                    mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
        }
        return mResources;
    }
@@ -531,9 +534,100 @@ public final class LoadedApk {
            }
        }

        // Rewrite the R 'constants' for all library apks.
        SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
                .getAssignedPackageIdentifiers();
        final int N = packageIdentifiers.size();
        for (int i = 0; i < N; i++) {
            final int id = packageIdentifiers.keyAt(i);
            if (id == 0x01 || id == 0x7f) {
                continue;
            }

            rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
        }

        return app;
    }

    private void rewriteIntField(Field field, int packageId) throws IllegalAccessException {
        int requiredModifiers = Modifier.STATIC | Modifier.PUBLIC;
        int bannedModifiers = Modifier.FINAL;

        int mod = field.getModifiers();
        if ((mod & requiredModifiers) != requiredModifiers ||
                (mod & bannedModifiers) != 0) {
            throw new IllegalArgumentException("Field " + field.getName() +
                    " is not rewritable");
        }

        if (field.getType() != int.class && field.getType() != Integer.class) {
            throw new IllegalArgumentException("Field " + field.getName() +
                    " is not an integer");
        }

        try {
            int resId = field.getInt(null);
            field.setInt(null, (resId & 0x00ffffff) | (packageId << 24));
        } catch (IllegalAccessException e) {
            // This should not occur (we check above if we can write to it)
            throw new IllegalArgumentException(e);
        }
    }

    private void rewriteIntArrayField(Field field, int packageId) {
        int requiredModifiers = Modifier.STATIC | Modifier.PUBLIC;

        if ((field.getModifiers() & requiredModifiers) != requiredModifiers) {
            throw new IllegalArgumentException("Field " + field.getName() +
                    " is not rewritable");
        }

        if (field.getType() != int[].class) {
            throw new IllegalArgumentException("Field " + field.getName() +
                    " is not an integer array");
        }

        try {
            int[] array = (int[]) field.get(null);
            for (int i = 0; i < array.length; i++) {
                array[i] = (array[i] & 0x00ffffff) | (packageId << 24);
            }
        } catch (IllegalAccessException e) {
            // This should not occur (we check above if we can write to it)
            throw new IllegalArgumentException(e);
        }
    }

    private void rewriteRValues(ClassLoader cl, String packageName, int id) {
        try {
            final Class<?> rClazz = cl.loadClass(packageName + ".R");
            Class<?>[] declaredClasses = rClazz.getDeclaredClasses();
            for (Class<?> clazz : declaredClasses) {
                try {
                    if (clazz.getSimpleName().equals("styleable")) {
                        for (Field field : clazz.getDeclaredFields()) {
                            if (field.getType() == int[].class) {
                                rewriteIntArrayField(field, id);
                            }
                        }

                    } else {
                        for (Field field : clazz.getDeclaredFields()) {
                            rewriteIntField(field, id);
                        }
                    }
                } catch (Exception e) {
                    throw new IllegalArgumentException("Failed to rewrite R values for " +
                            clazz.getName(), e);
                }
            }

        } catch (Exception e) {
            throw new IllegalArgumentException("Failed to rewrite R values", e);
        }
    }

    public void removeContextRegistrations(Context context,
            String who, String what) {
        final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
Loading