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

Commit b7c4782c authored by Narayan Kamath's avatar Narayan Kamath Committed by Android (Google) Code Review
Browse files

Merge "PackageParser: String interning fixes."

parents 8f52705b 07ac1442
Loading
Loading
Loading
Loading
+67 −7
Original line number Diff line number Diff line
@@ -2745,15 +2745,15 @@ public class PackageParser {
        String cls = clsSeq.toString();
        char c = cls.charAt(0);
        if (c == '.') {
            return (pkg + cls).intern();
            return pkg + cls;
        }
        if (cls.indexOf('.') < 0) {
            StringBuilder b = new StringBuilder(pkg);
            b.append('.');
            b.append(cls);
            return b.toString().intern();
            return b.toString();
        }
        return cls.intern();
        return cls;
    }

    private static String buildCompoundName(String pkg,
@@ -2773,7 +2773,7 @@ public class PackageParser {
                        + pkg + ": " + nameError;
                return null;
            }
            return (pkg + proc).intern();
            return pkg + proc;
        }
        String nameError = validateName(proc, true, false);
        if (nameError != null && !"system".equals(proc)) {
@@ -2781,7 +2781,7 @@ public class PackageParser {
                    + pkg + ": " + nameError;
            return null;
        }
        return proc.intern();
        return proc;
    }

    private static String buildProcessName(String pkg, String defProc,
@@ -5083,7 +5083,7 @@ public class PackageParser {
            if (v != null) {
                if (v.type == TypedValue.TYPE_STRING) {
                    CharSequence cs = v.coerceToString();
                    data.putString(name, cs != null ? cs.toString().intern() : null);
                    data.putString(name, cs != null ? cs.toString() : null);
                } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
                    data.putBoolean(name, v.data != 0);
                } else if (v.type >= TypedValue.TYPE_FIRST_INT
@@ -5866,7 +5866,7 @@ public class PackageParser {
            // We use the boot classloader for all classes that we load.
            final ClassLoader boot = Object.class.getClassLoader();

            packageName = dest.readString();
            packageName = dest.readString().intern();
            manifestPackageName = dest.readString();
            splitNames = dest.readStringArray();
            volumeUuid = dest.readString();
@@ -5879,6 +5879,9 @@ public class PackageParser {
            splitPrivateFlags = dest.createIntArray();
            baseHardwareAccelerated = (dest.readInt() == 1);
            applicationInfo = dest.readParcelable(boot);
            if (applicationInfo.permission != null) {
                applicationInfo.permission = applicationInfo.permission.intern();
            }

            // We don't serialize the "owner" package and the application info object for each of
            // these components, in order to save space and to avoid circular dependencies while
@@ -5899,7 +5902,10 @@ public class PackageParser {
            fixupOwner(instrumentation);

            dest.readStringList(requestedPermissions);
            internStringArrayList(requestedPermissions);
            protectedBroadcasts = dest.createStringArrayList();
            internStringArrayList(protectedBroadcasts);

            parentPackage = dest.readParcelable(boot);

            childPackages = new ArrayList<>();
@@ -5909,16 +5915,23 @@ public class PackageParser {
            }

            staticSharedLibName = dest.readString();
            if (staticSharedLibName != null) {
                staticSharedLibName = staticSharedLibName.intern();
            }
            staticSharedLibVersion = dest.readInt();
            libraryNames = dest.createStringArrayList();
            internStringArrayList(libraryNames);
            usesLibraries = dest.createStringArrayList();
            internStringArrayList(usesLibraries);
            usesOptionalLibraries = dest.createStringArrayList();
            internStringArrayList(usesOptionalLibraries);
            usesLibraryFiles = dest.readStringArray();

            final int libCount = dest.readInt();
            if (libCount > 0) {
                usesStaticLibraries = new ArrayList<>(libCount);
                dest.readStringList(usesStaticLibraries);
                internStringArrayList(usesStaticLibraries);
                usesStaticLibrariesVersions = new int[libCount];
                dest.readIntArray(usesStaticLibrariesVersions);
                usesStaticLibrariesCertDigests = new String[libCount];
@@ -5937,7 +5950,13 @@ public class PackageParser {
            mAppMetaData = dest.readBundle();
            mVersionCode = dest.readInt();
            mVersionName = dest.readString();
            if (mVersionName != null) {
                mVersionName = mVersionName.intern();
            }
            mSharedUserId = dest.readString();
            if (mSharedUserId != null) {
                mSharedUserId = mSharedUserId.intern();
            }
            mSharedUserLabel = dest.readInt();

            mSignatures = (Signature[]) dest.readParcelableArray(boot, Signature.class);
@@ -5988,6 +6007,15 @@ public class PackageParser {
            restrictUpdateHash = dest.createByteArray();
        }

        private static void internStringArrayList(List<String> list) {
            if (list != null) {
                final int N = list.size();
                for (int i = 0; i < N; ++i) {
                    list.set(i, list.get(i).intern());
                }
            }
        }

        /**
         * Sets the package owner and the the {@code applicationInfo} for every component
         * owner by this package.
@@ -6375,6 +6403,10 @@ public class PackageParser {
            super(in);
            final ClassLoader boot = Object.class.getClassLoader();
            info = in.readParcelable(boot);
            if (info.group != null) {
                info.group = info.group.intern();
            }

            tree = (in.readInt() == 1);
            group = in.readParcelable(boot);
        }
@@ -6651,6 +6683,10 @@ public class PackageParser {
            for (ActivityIntentInfo aii : intents) {
                aii.activity = this;
            }

            if (info.permission != null) {
                info.permission = info.permission.intern();
            }
        }

        public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Activity>() {
@@ -6735,6 +6771,10 @@ public class PackageParser {
            for (ServiceIntentInfo aii : intents) {
                aii.service = this;
            }

            if (info.permission != null) {
                info.permission = info.permission.intern();
            }
        }

        public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Service>() {
@@ -6816,6 +6856,18 @@ public class PackageParser {
            for (ProviderIntentInfo aii : intents) {
                aii.provider = this;
            }

            if (info.readPermission != null) {
                info.readPermission = info.readPermission.intern();
            }

            if (info.writePermission != null) {
                info.writePermission = info.writePermission.intern();
            }

            if (info.authority != null) {
                info.authority = info.authority.intern();
            }
        }

        public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Provider>() {
@@ -6888,6 +6940,14 @@ public class PackageParser {
        private Instrumentation(Parcel in) {
            super(in);
            info = in.readParcelable(Object.class.getClassLoader());

            if (info.targetPackage != null) {
                info.targetPackage = info.targetPackage.intern();
            }

            if (info.targetProcess != null) {
                info.targetProcess = info.targetProcess.intern();
            }
        }

        public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Instrumentation>() {
+63 −25
Original line number Diff line number Diff line
@@ -140,6 +140,36 @@ public class PackageParserTest {
        assertAllFieldsExist(deserialized);
    }

    @Test
    public void test_stringInterning() throws Exception {
        PackageParser.Package pkg = new PackageParser.Package("foo");
        setKnownFields(pkg);

        Parcel p = Parcel.obtain();
        pkg.writeToParcel(p, 0 /* flags */);

        p.setDataPosition(0);
        PackageParser.Package deserialized = new PackageParser.Package(p);

        p.setDataPosition(0);
        PackageParser.Package deserialized2 = new PackageParser.Package(p);

        assertSame(deserialized.packageName, deserialized2.packageName);
        assertSame(deserialized.applicationInfo.permission,
                deserialized2.applicationInfo.permission);
        assertSame(deserialized.requestedPermissions.get(0),
                deserialized2.requestedPermissions.get(0));
        assertSame(deserialized.protectedBroadcasts.get(0),
                deserialized2.protectedBroadcasts.get(0));
        assertSame(deserialized.usesLibraries.get(0),
                deserialized2.usesLibraries.get(0));
        assertSame(deserialized.usesOptionalLibraries.get(0),
                deserialized2.usesOptionalLibraries.get(0));
        assertSame(deserialized.mVersionName, deserialized2.mVersionName);
        assertSame(deserialized.mSharedUserId, deserialized2.mSharedUserId);
    }


    /**
     * A trivial subclass of package parser that only caches the package name, and throws away
     * all other information.
@@ -407,11 +437,11 @@ public class PackageParserTest {
        pkg.mTrustedOverlay = true;
        pkg.use32bitAbi = true;
        pkg.packageName = "foo";
        pkg.splitNames = new String[] { "foo" };
        pkg.volumeUuid = "foo";
        pkg.codePath = "foo";
        pkg.baseCodePath = "foo";
        pkg.splitCodePaths = new String[] { "foo" };
        pkg.splitNames = new String[] { "foo2" };
        pkg.volumeUuid = "foo3";
        pkg.codePath = "foo4";
        pkg.baseCodePath = "foo5";
        pkg.splitCodePaths = new String[] { "foo6" };
        pkg.splitRevisionCodes = new int[] { 100 };
        pkg.splitFlags = new int[] { 100 };
        pkg.splitPrivateFlags = new int[] { 100 };
@@ -428,48 +458,55 @@ public class PackageParserTest {
        pkg.providers.add(new PackageParser.Provider(dummy, new ProviderInfo()));
        pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo()));
        pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo()));
        pkg.requestedPermissions.add("foo");
        pkg.requestedPermissions.add("foo7");

        pkg.protectedBroadcasts = new ArrayList<>();
        pkg.protectedBroadcasts.add("foo");
        pkg.protectedBroadcasts.add("foo8");

        pkg.parentPackage = new PackageParser.Package("foo");
        pkg.parentPackage = new PackageParser.Package("foo9");

        pkg.childPackages = new ArrayList<>();
        pkg.childPackages.add(new PackageParser.Package("bar"));

        pkg.staticSharedLibName = "foo23";
        pkg.staticSharedLibVersion = 100;
        pkg.usesStaticLibraries = new ArrayList<>();
        pkg.usesStaticLibraries.add("foo23");
        pkg.usesStaticLibrariesCertDigests = new String[] { "digest" };
        pkg.usesStaticLibrariesVersions = new int[] { 100 };

        pkg.libraryNames = new ArrayList<>();
        pkg.libraryNames.add("foo");
        pkg.libraryNames.add("foo10");

        pkg.usesLibraries = new ArrayList<>();
        pkg.usesLibraries.add("foo");
        pkg.usesLibraries.add("foo11");

        pkg.usesOptionalLibraries = new ArrayList<>();
        pkg.usesOptionalLibraries.add("foo");
        pkg.usesOptionalLibraries.add("foo12");

        pkg.usesLibraryFiles = new String[] { "foo "};
        pkg.usesLibraryFiles = new String[] { "foo13"};

        pkg.mOriginalPackages = new ArrayList<>();
        pkg.mOriginalPackages.add("foo");
        pkg.mOriginalPackages.add("foo14");

        pkg.mRealPackage = "foo";
        pkg.mRealPackage = "foo15";

        pkg.mAdoptPermissions = new ArrayList<>();
        pkg.mAdoptPermissions.add("foo");
        pkg.mAdoptPermissions.add("foo16");

        pkg.mAppMetaData = new Bundle();
        pkg.mVersionName = "foo";
        pkg.mSharedUserId = "foo";
        pkg.mVersionName = "foo17";
        pkg.mSharedUserId = "foo18";
        pkg.mSignatures = new Signature[] { new Signature(new byte[16]) };
        pkg.mCertificates = new Certificate[][] { new Certificate[] { null }};
        pkg.mExtras = new Bundle();
        pkg.mRestrictedAccountType = "foo";
        pkg.mRequiredAccountType = "foo";
        pkg.mOverlayTarget = "foo";
        pkg.mRestrictedAccountType = "foo19";
        pkg.mRequiredAccountType = "foo20";
        pkg.mOverlayTarget = "foo21";
        pkg.mSigningKeys = new ArraySet<>();
        pkg.mUpgradeKeySets = new ArraySet<>();
        pkg.mKeySetMapping = new ArrayMap<>();
        pkg.cpuAbiOverride = "foo";
        pkg.cpuAbiOverride = "foo22";
        pkg.restrictUpdateHash = new byte[16];

        pkg.preferredActivityFilters = new ArrayList<>();
@@ -504,7 +541,7 @@ public class PackageParserTest {
                // Sanity check for list fields: Assume they're non-null and contain precisely
                // one element.
                List<?> list = (List<?>) f.get(pkg);
                assertNotNull(list);
                assertNotNull("List was null: " + f, list);
                assertEquals(1, list.size());
            } else if (fieldType.getComponentType() != null) {
                // Sanity check for array fields: Assume they're non-null and contain precisely
@@ -514,15 +551,16 @@ public class PackageParserTest {
            } else if (fieldType == String.class) {
                // String fields: Check that they're set to "foo".
                String value = (String) f.get(pkg);
                assertEquals("foo", value);

                assertTrue("Bad value for field: " + f, value != null && value.startsWith("foo"));
            } else if (fieldType == int.class) {
                // int fields: Check that they're set to 100.
                int value = (int) f.get(pkg);
                assertEquals(100, value);
                assertEquals("Bad value for field: " + f, 100, value);
            } else {
                // All other fields: Check that they're set.
                Object o = f.get(pkg);
                assertNotNull("Field was null: " + f.getName(), o);
                assertNotNull("Field was null: " + f, o);
            }
        }
    }