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

Commit ea22a5a5 authored by Presubmit Automerger Backend's avatar Presubmit Automerger Backend
Browse files

[automerge] Use strings in shared library updatability attributes 2p: a40064f2

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

Bug: 191978330
Change-Id: Ie1fa6d6efaabb0f2db5c4b091223c79ea4ce2d1e
parents 7da27688 a40064f2
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);