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

Commit 19630d16 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Support conditional removal of oahl from bootclasspath"

parents a8e46414 beee5dcd
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -631,6 +631,11 @@ java_library {
        ],
    },

    // See comment on framework-oahl-backward-compatibility module below
    exclude_srcs: [
        "core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java",
    ],

    no_framework_libs: true,
    libs: [
        "conscrypt",
@@ -666,6 +671,18 @@ java_library {
    ],
}

// A temporary build target that is conditionally included on the bootclasspath if
// org.apache.http.legacy library has been removed and which provides support for
// maintaining backwards compatibility for APKs that target pre-P and depend on
// org.apache.http.legacy classes. This is used iff REMOVE_OAHL_FROM_BCP=true is
// specified on the build command line.
java_library {
    name: "framework-oahl-backward-compatibility",
    srcs: [
        "core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java",
    ],
}

genrule {
    name: "framework-statslog-gen",
    tools: ["stats-log-api-gen"],
+66 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.content.pm;

import android.content.pm.PackageParser.Package;
import android.os.Build;

import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;

/**
 * Updates a package to ensure that if it targets < P that the org.apache.http.legacy library is
 * included by default.
 *
 * <p>This is separated out so that it can be conditionally included at build time depending on
 * whether org.apache.http.legacy is on the bootclasspath or not. In order to include this at
 * build time, and remove org.apache.http.legacy from the bootclasspath pass
 * REMOVE_OAHL_FROM_BCP=true on the build command line, otherwise this class will not be included
 * and the
 *
 * @hide
 */
@VisibleForTesting
public class OrgApacheHttpLegacyUpdater extends PackageSharedLibraryUpdater {

    private static final String APACHE_HTTP_LEGACY = "org.apache.http.legacy";

    @Override
    public void updatePackage(Package pkg) {
        ArrayList<String> usesLibraries = pkg.usesLibraries;
        ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;

        // Packages targeted at <= O_MR1 expect the classes in the org.apache.http.legacy library
        // to be accessible so this maintains backward compatibility by adding the
        // org.apache.http.legacy library to those packages.
        if (apkTargetsApiLevelLessThanOrEqualToOMR1(pkg)) {
            boolean apacheHttpLegacyPresent = isLibraryPresent(
                    usesLibraries, usesOptionalLibraries, APACHE_HTTP_LEGACY);
            if (!apacheHttpLegacyPresent) {
                usesLibraries = prefix(usesLibraries, APACHE_HTTP_LEGACY);
            }
        }

        pkg.usesLibraries = usesLibraries;
        pkg.usesOptionalLibraries = usesOptionalLibraries;
    }

    private static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(Package pkg) {
        int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
        return targetSdkVersion <= Build.VERSION_CODES.O_MR1;
    }
}
+111 −43
Original line number Diff line number Diff line
@@ -16,15 +16,14 @@

package android.content.pm;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PackageParser.Package;
import android.os.Build;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * Modifies {@link Package} in order to maintain backwards compatibility.
@@ -32,13 +31,60 @@ import java.util.ArrayList;
 * @hide
 */
@VisibleForTesting
public class PackageBackwardCompatibility {
public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {

    private static final String TAG = PackageBackwardCompatibility.class.getSimpleName();

    private static final String ANDROID_TEST_MOCK = "android.test.mock";

    private static final String ANDROID_TEST_RUNNER = "android.test.runner";

    private static final String APACHE_HTTP_LEGACY = "org.apache.http.legacy";
    private static final PackageBackwardCompatibility INSTANCE;

    static {
        String className = "android.content.pm.OrgApacheHttpLegacyUpdater";
        Class<? extends PackageSharedLibraryUpdater> clazz;
        try {
            clazz = (PackageBackwardCompatibility.class.getClassLoader()
                    .loadClass(className)
                    .asSubclass(PackageSharedLibraryUpdater.class));
        } catch (ClassNotFoundException e) {
            Log.i(TAG, "Could not find " + className + ", ignoring");
            clazz = null;
        }

        boolean hasOrgApacheHttpLegacy = false;
        final List<PackageSharedLibraryUpdater> packageUpdaters = new ArrayList<>();
        if (clazz == null) {
            // Add an updater that will remove any references to org.apache.http.library from the
            // package so that it does not try and load the library when it is on the
            // bootclasspath.
            packageUpdaters.add(new RemoveUnnecessaryOrgApacheHttpLegacyLibrary());
        } else {
            try {
                packageUpdaters.add(clazz.getConstructor().newInstance());
                hasOrgApacheHttpLegacy = true;
            } catch (ReflectiveOperationException e) {
                throw new IllegalStateException("Could not create instance of " + className, e);
            }
        }

        packageUpdaters.add(new AndroidTestRunnerSplitUpdater());

        PackageSharedLibraryUpdater[] updaterArray = packageUpdaters
                .toArray(new PackageSharedLibraryUpdater[0]);
        INSTANCE = new PackageBackwardCompatibility(hasOrgApacheHttpLegacy, updaterArray);
    }

    private final boolean mRemovedOAHLFromBCP;

    private final PackageSharedLibraryUpdater[] mPackageUpdaters;

    public PackageBackwardCompatibility(boolean removedOAHLFromBCP,
            PackageSharedLibraryUpdater[] packageUpdaters) {
        this.mRemovedOAHLFromBCP = removedOAHLFromBCP;
        this.mPackageUpdaters = packageUpdaters;
    }

    /**
     * Modify the shared libraries in the supplied {@link Package} to maintain backwards
@@ -48,25 +94,47 @@ public class PackageBackwardCompatibility {
     */
    @VisibleForTesting
    public static void modifySharedLibraries(Package pkg) {
        ArrayList<String> usesLibraries = pkg.usesLibraries;
        ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;
        INSTANCE.updatePackage(pkg);
    }

    @Override
    public void updatePackage(Package pkg) {

        // Packages targeted at <= O_MR1 expect the classes in the org.apache.http.legacy library
        // to be accessible so this maintains backward compatibility by adding the
        // org.apache.http.legacy library to those packages.
        if (apkTargetsApiLevelLessThanOrEqualToOMR1(pkg)) {
            boolean apacheHttpLegacyPresent = isLibraryPresent(
                    usesLibraries, usesOptionalLibraries, APACHE_HTTP_LEGACY);
            if (!apacheHttpLegacyPresent) {
                usesLibraries = prefix(usesLibraries, APACHE_HTTP_LEGACY);
        for (PackageSharedLibraryUpdater packageUpdater : mPackageUpdaters) {
            packageUpdater.updatePackage(pkg);
        }
    }

    /**
     * True if the org.apache.http.legacy has been removed the bootclasspath, false otherwise.
     */
    public static boolean removeOAHLFromBCP() {
        return INSTANCE.mRemovedOAHLFromBCP;
    }

    /**
     * Add android.test.mock dependency for any APK that depends on android.test.runner.
     *
     * <p>This is needed to maintain backwards compatibility as in previous versions of Android the
     * android.test.runner library included the classes from android.test.mock which have since
     * been split out into a separate library.
     *
     * @hide
     */
    @VisibleForTesting
    public static class AndroidTestRunnerSplitUpdater extends PackageSharedLibraryUpdater {

        @Override
        public void updatePackage(Package pkg) {
            ArrayList<String> usesLibraries = pkg.usesLibraries;
            ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;

            // android.test.runner has a dependency on android.test.mock so if android.test.runner
            // is present but android.test.mock is not then add android.test.mock.
            boolean androidTestMockPresent = isLibraryPresent(
                    usesLibraries, usesOptionalLibraries, ANDROID_TEST_MOCK);
        if (ArrayUtils.contains(usesLibraries, ANDROID_TEST_RUNNER) && !androidTestMockPresent) {
            if (ArrayUtils.contains(usesLibraries, ANDROID_TEST_RUNNER)
                    && !androidTestMockPresent) {
                usesLibraries.add(ANDROID_TEST_MOCK);
            }
            if (ArrayUtils.contains(usesOptionalLibraries, ANDROID_TEST_RUNNER)
@@ -77,23 +145,23 @@ public class PackageBackwardCompatibility {
            pkg.usesLibraries = usesLibraries;
            pkg.usesOptionalLibraries = usesOptionalLibraries;
        }

    private static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(Package pkg) {
        int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
        return targetSdkVersion <= Build.VERSION_CODES.O_MR1;
    }

    private static boolean isLibraryPresent(ArrayList<String> usesLibraries,
            ArrayList<String> usesOptionalLibraries, String apacheHttpLegacy) {
        return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
                || ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
    }
    /**
     * Remove any usages of org.apache.http.legacy from the shared library as the library is on the
     * bootclasspath.
     */
    @VisibleForTesting
    public static class RemoveUnnecessaryOrgApacheHttpLegacyLibrary
            extends PackageSharedLibraryUpdater {

        private static final String APACHE_HTTP_LEGACY = "org.apache.http.legacy";

    private static @NonNull <T> ArrayList<T> prefix(@Nullable ArrayList<T> cur, T val) {
        if (cur == null) {
            cur = new ArrayList<>();
        @Override
        public void updatePackage(Package pkg) {
            pkg.usesLibraries = ArrayUtils.remove(pkg.usesLibraries, APACHE_HTTP_LEGACY);
            pkg.usesOptionalLibraries =
                    ArrayUtils.remove(pkg.usesOptionalLibraries, APACHE_HTTP_LEGACY);
        }
        cur.add(0, val);
        return cur;
    }
}
+55 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.content.pm;

import android.annotation.NonNull;
import android.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

import java.util.ArrayList;

/**
 * Base for classes that update a {@link PackageParser.Package}'s shared libraries.
 *
 * @hide
 */
@VisibleForTesting
public abstract class PackageSharedLibraryUpdater {

    /**
     * Update the package's shared libraries.
     *
     * @param pkg the package to update.
     */
    public abstract void updatePackage(PackageParser.Package pkg);

    static @NonNull
            <T> ArrayList<T> prefix(@Nullable ArrayList<T> cur, T val) {
        if (cur == null) {
            cur = new ArrayList<>();
        }
        cur.add(0, val);
        return cur;
    }

    static boolean isLibraryPresent(ArrayList<String> usesLibraries,
            ArrayList<String> usesOptionalLibraries, String apacheHttpLegacy) {
        return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
                || ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -53,6 +53,10 @@ LOCAL_JAVA_LIBRARIES := \
    android.test.base \
    android.test.mock \

ifeq ($(REMOVE_OAHL_FROM_BCP),true)
LOCAL_JAVA_LIBRARIES += framework-oahl-backward-compatibility
endif

LOCAL_PACKAGE_NAME := FrameworksCoreTests
LOCAL_COMPATIBILITY_SUITE := device-tests

Loading