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

Commit 7faf546f authored by Pedro Loureiro's avatar Pedro Loureiro Committed by Automerger Merge Worker
Browse files

Merge "Use strings in shared library updatability attributes" into tm-dev am:...

Merge "Use strings in shared library updatability attributes" into tm-dev am: 5e86cee0 am: aec26f69

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17201283



Change-Id: I3a7ebd328d3c493efb29387b258ea12f28ebee78
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 6214bc05 aec26f69
Loading
Loading
Loading
Loading
+27 −27
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.util.Xml;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.build.UnboundedSdkLevel;

import libcore.io.IoUtils;
import libcore.util.EmptyArray;
@@ -126,7 +127,7 @@ public class SystemConfig {
         *
         * <p>0 means not specified.
         */
        public final int onBootclasspathSince;
        public final String onBootclasspathSince;

        /**
         * SDK version this library was removed from the BOOTCLASSPATH.
@@ -138,7 +139,7 @@ public class SystemConfig {
         *
         * <p>0 means not specified.
         */
        public final int onBootclasspathBefore;
        public final String onBootclasspathBefore;

        /**
         * Declares whether this library can be safely ignored from <uses-library> tags.
@@ -155,19 +156,19 @@ public class SystemConfig {
        @VisibleForTesting
        public SharedLibraryEntry(String name, String filename, String[] dependencies,
                boolean isNative) {
            this(name, filename, dependencies, 0 /* onBootclasspathSince */,
                    0 /* onBootclasspathBefore */, isNative);
            this(name, filename, dependencies, null /* onBootclasspathSince */,
                    null /* onBootclasspathBefore */, isNative);
        }

        @VisibleForTesting
        public SharedLibraryEntry(String name, String filename, String[] dependencies,
                int onBootclasspathSince, int onBootclassPathBefore) {
            this(name, filename, dependencies, onBootclasspathSince, onBootclassPathBefore,
                String onBootclasspathSince, String onBootclasspathBefore) {
            this(name, filename, dependencies, onBootclasspathSince, onBootclasspathBefore,
                    false /* isNative */);
        }

        SharedLibraryEntry(String name, String filename, String[] dependencies,
                int onBootclasspathSince, int onBootclasspathBefore, boolean isNative) {
                String onBootclasspathSince, String onBootclasspathBefore, boolean isNative) {
            this.name = name;
            this.filename = filename;
            this.dependencies = dependencies;
@@ -175,16 +176,14 @@ public class SystemConfig {
            this.onBootclasspathBefore = onBootclasspathBefore;
            this.isNative = isNative;

            canBeSafelyIgnored = this.onBootclasspathSince != 0
                    && isSdkAtLeast(this.onBootclasspathSince);
        }

        private static boolean isSdkAtLeast(int level) {
            if ("REL".equals(Build.VERSION.CODENAME)) {
                return Build.VERSION.SDK_INT >= level;
            }
            return level == Build.VERSION_CODES.CUR_DEVELOPMENT
                    || Build.VERSION.SDK_INT >= level;
            // this entry can be ignored if either:
            // - onBootclasspathSince is set and we are at or past that SDK
            // - onBootclasspathBefore is set and we are before that SDK
            canBeSafelyIgnored =
                    (this.onBootclasspathSince != null
                            && UnboundedSdkLevel.isAtLeast(this.onBootclasspathSince))
                            || (this.onBootclasspathBefore != null
                            && !UnboundedSdkLevel.isAtLeast(this.onBootclasspathBefore));
        }
    }

@@ -878,10 +877,8 @@ public class SystemConfig {
                            String lname = parser.getAttributeValue(null, "name");
                            String lfile = parser.getAttributeValue(null, "file");
                            String ldependency = parser.getAttributeValue(null, "dependency");
                            int minDeviceSdk = XmlUtils.readIntAttribute(parser, "min-device-sdk",
                                    0);
                            int maxDeviceSdk = XmlUtils.readIntAttribute(parser, "max-device-sdk",
                                    0);
                            String minDeviceSdk = parser.getAttributeValue(null, "min-device-sdk");
                            String maxDeviceSdk = parser.getAttributeValue(null, "max-device-sdk");
                            if (lname == null) {
                                Slog.w(TAG, "<" + name + "> without name in " + permFile + " at "
                                        + parser.getPositionDescription());
@@ -889,15 +886,18 @@ public class SystemConfig {
                                Slog.w(TAG, "<" + name + "> without file in " + permFile + " at "
                                        + parser.getPositionDescription());
                            } else {
                                boolean allowedMinSdk = minDeviceSdk <= Build.VERSION.SDK_INT;
                                boolean allowedMinSdk =
                                        minDeviceSdk == null || UnboundedSdkLevel.isAtLeast(
                                                minDeviceSdk);
                                boolean allowedMaxSdk =
                                        maxDeviceSdk == 0 || maxDeviceSdk >= Build.VERSION.SDK_INT;
                                        maxDeviceSdk == null || UnboundedSdkLevel.isAtMost(
                                                maxDeviceSdk);
                                final boolean exists = new File(lfile).exists();
                                if (allowedMinSdk && allowedMaxSdk && exists) {
                                    int bcpSince = XmlUtils.readIntAttribute(parser,
                                            "on-bootclasspath-since", 0);
                                    int bcpBefore = XmlUtils.readIntAttribute(parser,
                                            "on-bootclasspath-before", 0);
                                    String bcpSince = parser.getAttributeValue(null,
                                            "on-bootclasspath-since");
                                    String bcpBefore = parser.getAttributeValue(null,
                                            "on-bootclasspath-before");
                                    SharedLibraryEntry entry = new SharedLibraryEntry(lname, lfile,
                                            ldependency == null
                                                    ? new String[0] : ldependency.split(":"),
+21 −2
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.pm.parsing.library;
import android.util.ArrayMap;

import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.build.UnboundedSdkLevel;
import com.android.server.SystemConfig;
import com.android.server.pm.parsing.pkg.ParsedPackage;

@@ -51,8 +52,11 @@ public class ApexSharedLibraryUpdater extends PackageSharedLibraryUpdater {

    private void updateSharedLibraryForPackage(SystemConfig.SharedLibraryEntry entry,
            ParsedPackage parsedPackage) {
        if (entry.onBootclasspathBefore != 0
                && parsedPackage.getTargetSdkVersion() < entry.onBootclasspathBefore) {
        if (entry.onBootclasspathBefore != null
                && isTargetSdkAtMost(
                        parsedPackage.getTargetSdkVersion(),
                        entry.onBootclasspathBefore)
                && UnboundedSdkLevel.isAtLeast(entry.onBootclasspathBefore)) {
            // this package targets an API where this library was in the BCP, so add
            // the library transparently in case the package is using it
            prefixRequiredLibrary(parsedPackage, entry.name);
@@ -64,4 +68,19 @@ public class ApexSharedLibraryUpdater extends PackageSharedLibraryUpdater {
            removeLibrary(parsedPackage, entry.name);
        }
    }

    private static boolean isTargetSdkAtMost(int targetSdk, String onBcpBefore) {
        if (isCodename(onBcpBefore)) {
            return targetSdk < 10000;
        }
        return targetSdk < Integer.parseInt(onBcpBefore);
    }

    private static boolean isCodename(String version) {
        if (version.length() == 0) {
            throw new IllegalArgumentException();
        }
        // assume Android codenames start with upper case letters.
        return Character.isUpperCase((version.charAt(0)));
    }
}
+103 −14
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTest {

    private static final String SDK_INT_PLUS_ONE = "" + (Build.VERSION.SDK_INT + 1);
    private static final String SDK_INT_PLUS_TWO = "" + (Build.VERSION.SDK_INT + 2);
    private final ArrayMap<String, SystemConfig.SharedLibraryEntry> mSharedLibraries =
            new ArrayMap<>(8);

@@ -51,14 +53,19 @@ public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTes

    private void installSharedLibraries() throws Exception {
        mSharedLibraries.clear();
        insertLibrary("foo", 0, 0);
        insertLibrary("fooBcpSince30", 30, 0);
        insertLibrary("fooBcpBefore30", 0, 30);
        insertLibrary("fooFromFuture", Build.VERSION.SDK_INT + 2, 0);
        insertLibrary("foo", null, null);
        insertLibrary("fooBcpSince30", "30", null);
        insertLibrary("fooBcpBefore30", null, "30");
        // simulate libraries being added to the BCP in a future release
        insertLibrary("fooSinceFuture", SDK_INT_PLUS_ONE, null);
        insertLibrary("fooSinceFutureCodename", "Z", null);
        // simulate libraries being removed from the BCP in a future release
        insertLibrary("fooBcpBeforeFuture", null, SDK_INT_PLUS_ONE);
        insertLibrary("fooBcpBeforeFutureCodename", null, "Z");
    }

    private void insertLibrary(String libraryName, int onBootclasspathSince,
            int onBootclasspathBefore) {
    private void insertLibrary(String libraryName, String onBootclasspathSince,
            String onBootclasspathBefore) {
        mSharedLibraries.put(libraryName, new SystemConfig.SharedLibraryEntry(
                libraryName,
                "foo.jar",
@@ -112,7 +119,7 @@ public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTes
    }

    @Test
    public void testBcpSince11kNotAppliedWithoutLibrary() {
    public void testBcpSinceFutureNotAppliedWithoutLibrary() {
        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.R)
                .hideAsParsed());
@@ -128,15 +135,17 @@ public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTes
    }

    @Test
    public void testBcpSince11kNotAppliedWithLibrary() {
    public void testBcpSinceFutureNotAppliedWithLibrary() {
        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.R)
                .addUsesLibrary("fooFromFuture")
                .addUsesLibrary("fooSinceFuture")
                .addUsesLibrary("fooSinceFutureCodename")
                .hideAsParsed());

        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.R)
                .addUsesLibrary("fooFromFuture")
                .addUsesLibrary("fooSinceFuture")
                .addUsesLibrary("fooSinceFutureCodename")
                .hideAsParsed())
                .hideAsFinal();

@@ -183,7 +192,7 @@ public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTes
     */
    @Test
    public void testBcpRemovedThenAddedPast() {
        insertLibrary("fooBcpRemovedThenAdded", 30, 28);
        insertLibrary("fooBcpRemovedThenAdded", "30", "28");

        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.N)
@@ -207,7 +216,8 @@ public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTes
     */
    @Test
    public void testBcpRemovedThenAddedMiddle_targetQ() {
        insertLibrary("fooBcpRemovedThenAdded", Build.VERSION.SDK_INT + 1, 30);
        insertLibrary("fooBcpRemovedThenAdded", SDK_INT_PLUS_ONE, "30");
        insertLibrary("fooBcpRemovedThenAddedCodename", "Z", "30");

        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.Q)
@@ -217,6 +227,7 @@ public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTes
                .setTargetSdkVersion(Build.VERSION_CODES.Q)
                .addUsesLibrary("fooBcpRemovedThenAdded")
                .addUsesLibrary("fooBcpBefore30")
                .addUsesLibrary("fooBcpRemovedThenAddedCodename")
                .hideAsParsed())
                .hideAsFinal();

@@ -232,7 +243,8 @@ public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTes
     */
    @Test
    public void testBcpRemovedThenAddedMiddle_targetR() {
        insertLibrary("fooBcpRemovedThenAdded", Build.VERSION.SDK_INT + 1, 30);
        insertLibrary("fooBcpRemovedThenAdded", SDK_INT_PLUS_ONE, "30");
        insertLibrary("fooBcpRemovedThenAddedCodename", "Z", "30");

        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.R)
@@ -256,7 +268,8 @@ public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTes
     */
    @Test
    public void testBcpRemovedThenAddedMiddle_targetR_usingLib() {
        insertLibrary("fooBcpRemovedThenAdded", Build.VERSION.SDK_INT + 1, 30);
        insertLibrary("fooBcpRemovedThenAdded", SDK_INT_PLUS_ONE, "30");
        insertLibrary("fooBcpRemovedThenAddedCodename", "Z", "30");

        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.R)
@@ -274,6 +287,82 @@ public class ApexSharedLibraryUpdaterTest extends PackageSharedLibraryUpdaterTes
        checkBackwardsCompatibility(before, after);
    }

    /**
     * Test a library that was first removed from the BCP [to a mainline module] and later was
     * moved back to the BCP via a mainline module update. Both things happening in future SDKs.
     */
    @Test
    public void testBcpRemovedThenAddedFuture() {
        insertLibrary("fooBcpRemovedThenAdded", SDK_INT_PLUS_TWO, SDK_INT_PLUS_ONE);
        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.R)
                .hideAsParsed());

        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.R)
                .hideAsParsed())
                .hideAsFinal();

        // in this example, we are at the point where the library is still in the BCP
        checkBackwardsCompatibility(before, after);
    }

    /**
     * Test a library that was first removed from the BCP [to a mainline module] and later was
     * moved back to the BCP via a mainline module update. Both things happening in future SDKs.
     */
    @Test
    public void testBcpRemovedThenAddedFuture_usingLib() {
        insertLibrary("fooBcpRemovedThenAdded", SDK_INT_PLUS_TWO, SDK_INT_PLUS_ONE);

        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Integer.parseInt(SDK_INT_PLUS_ONE))
                .addUsesLibrary("fooBcpRemovedThenAdded")
                .hideAsParsed());

        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Integer.parseInt(SDK_INT_PLUS_ONE))
                .hideAsParsed())
                .hideAsFinal();

        // in this example, we are at the point where the library was removed from the BCP
        checkBackwardsCompatibility(before, after);
    }

    @Test
    public void testBcpBeforeFuture() {
        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.R)
                .addUsesLibrary("fooBcpBeforeFuture")
                .addUsesLibrary("fooBcpBeforeFutureCodename")
                .hideAsParsed());

        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Build.VERSION_CODES.R)
                .hideAsParsed())
                .hideAsFinal();

        // in this example, we are at the point where the library was removed from the BCP
        checkBackwardsCompatibility(before, after);
    }

    @Test
    public void testBcpBeforeFuture_futureTargetSdk() {
        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Integer.parseInt(SDK_INT_PLUS_ONE))
                .addUsesLibrary("fooBcpBeforeFuture")
                .addUsesLibrary("fooBcpBeforeFutureCodename")
                .hideAsParsed());

        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                .setTargetSdkVersion(Integer.parseInt(SDK_INT_PLUS_ONE))
                .hideAsParsed())
                .hideAsFinal();

        // in this example, we are at the point where the library was removed from the BCP
        checkBackwardsCompatibility(before, after);
    }

    private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) {
        checkBackwardsCompatibility(before, after,
                () -> new ApexSharedLibraryUpdater(mSharedLibraries));
+42 −12
Original line number Diff line number Diff line
@@ -439,8 +439,30 @@ public class SystemConfigTest {
        parseSharedLibraries(contents);
        assertFooIsOnlySharedLibrary();
        SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
        assertThat(entry.onBootclasspathBefore).isEqualTo(10);
        assertThat(entry.onBootclasspathSince).isEqualTo(20);
        assertThat(entry.onBootclasspathBefore).isEqualTo("10");
        assertThat(entry.onBootclasspathSince).isEqualTo("20");
    }

    /**
     * Tests that readPermissions works correctly for a library with on-bootclasspath-before
     * and on-bootclasspath-since that uses codenames.
     */
    @Test
    public void readPermissions_allowLibs_parsesSimpleLibraryWithCodenames() throws IOException {
        String contents =
                "<permissions>\n"
                        + "    <library \n"
                        + "        name=\"foo\"\n"
                        + "        file=\"" + mFooJar + "\"\n"
                        + "        on-bootclasspath-before=\"Q\"\n"
                        + "        on-bootclasspath-since=\"W\"\n"
                        + "     />\n\n"
                        + " </permissions>";
        parseSharedLibraries(contents);
        assertFooIsOnlySharedLibrary();
        SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
        assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
        assertThat(entry.onBootclasspathSince).isEqualTo("W");
    }

    /**
@@ -461,8 +483,8 @@ public class SystemConfigTest {
        parseSharedLibraries(contents);
        assertFooIsOnlySharedLibrary();
        SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
        assertThat(entry.onBootclasspathBefore).isEqualTo(10);
        assertThat(entry.onBootclasspathSince).isEqualTo(20);
        assertThat(entry.onBootclasspathBefore).isEqualTo("10");
        assertThat(entry.onBootclasspathSince).isEqualTo("20");
    }

    /**
@@ -543,12 +565,20 @@ public class SystemConfigTest {
     */
    @Test
    public void readPermissions_allowLibs_allowsCurrentMaxSdk() throws IOException {
        // depending on whether this test is running before or after finalization, we need to
        // pass a different parameter
        String parameter;
        if ("REL".equals(Build.VERSION.CODENAME)) {
            parameter = "" + Build.VERSION.SDK_INT;
        } else {
            parameter = "ZZZ";
        }
        String contents =
                "<permissions>\n"
                + "    <library \n"
                + "        name=\"foo\"\n"
                + "        file=\"" + mFooJar + "\"\n"
                + "        max-device-sdk=\"" + Build.VERSION.SDK_INT + "\"\n"
                + "        max-device-sdk=\"" + parameter + "\"\n"
                + "     />\n\n"
                + " </permissions>";
        parseSharedLibraries(contents);