summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Paul Duffin <paulduffin@google.com> 2018-01-23 13:39:00 +0000
committer Paul Duffin <paulduffin@google.com> 2018-01-23 17:09:32 +0000
commitbeee5dcdfadf4d4b34d3d6ac733be3c420746c84 (patch)
treea942b5c97c49d91d977bd44776a53b1c0e422b68
parenta8c7794856c5794fa5b31cf5398b8f773650d6c7 (diff)
Support conditional removal of oahl from bootclasspath
This makes the runtime handling of the org.apache.http.legacy library conditional based on a build flag REMOVE_OAHL_FROM_BCP. When REMOVE_OAHL_FROM_BCP=true: * The framework-oahl-backward-compatibility is added to the bootclasspath instead of org.apache.http.legacy. * Any APK that targets pre-P has org.apache.http.legacy added to their library list. Otherwise: * The org.apache.http.legacy library is added to the bootclasspath. * Any APK that explicitly specifies that it depends on the org.apache.http.legacy library has the library removed as the classes are available at runtime. Tested both cases by building with or without the build flag, flashing, setting up, adding an account, adding a trusted place. Adding an account failed when REMOVE_OAHL_FROM_BCP=true. adb install -r -g out/target/product/marlin/testcases/FrameworksCoreTests/FrameworksCoreTests.apk adb shell am instrument -w -e class android.content.pm.PackageBackwardCompatibilityTest com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner Bug: 18027885 Bug: 72375096 Test: as above Change-Id: Ie88fb79da76d3cbbd27eaf820c872191ecba2b17
-rw-r--r--Android.bp17
-rw-r--r--core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java66
-rw-r--r--core/java/android/content/pm/PackageBackwardCompatibility.java154
-rw-r--r--core/java/android/content/pm/PackageSharedLibraryUpdater.java55
-rw-r--r--core/tests/coretests/Android.mk4
-rw-r--r--core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java66
6 files changed, 300 insertions, 62 deletions
diff --git a/Android.bp b/Android.bp
index 9e9faf2d7ffa..c775d15f6bb2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -630,6 +630,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",
@@ -665,6 +670,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"],
diff --git a/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java b/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java
new file mode 100644
index 000000000000..81041e9d3ba6
--- /dev/null
+++ b/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java
@@ -0,0 +1,66 @@
+/*
+ * 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;
+ }
+}
diff --git a/core/java/android/content/pm/PackageBackwardCompatibility.java b/core/java/android/content/pm/PackageBackwardCompatibility.java
index 8014c94d198d..9bdb78be5442 100644
--- a/core/java/android/content/pm/PackageBackwardCompatibility.java
+++ b/core/java/android/content/pm/PackageBackwardCompatibility.java
@@ -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,52 +94,74 @@ public class PackageBackwardCompatibility {
*/
@VisibleForTesting
public static void modifySharedLibraries(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);
- }
- }
+ INSTANCE.updatePackage(pkg);
+ }
- // 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) {
- usesLibraries.add(ANDROID_TEST_MOCK);
- }
- if (ArrayUtils.contains(usesOptionalLibraries, ANDROID_TEST_RUNNER)
- && !androidTestMockPresent) {
- usesOptionalLibraries.add(ANDROID_TEST_MOCK);
- }
+ @Override
+ public void updatePackage(Package pkg) {
- pkg.usesLibraries = usesLibraries;
- pkg.usesOptionalLibraries = usesOptionalLibraries;
+ for (PackageSharedLibraryUpdater packageUpdater : mPackageUpdaters) {
+ packageUpdater.updatePackage(pkg);
+ }
}
- private static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(Package pkg) {
- int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
- return targetSdkVersion <= Build.VERSION_CODES.O_MR1;
+ /**
+ * True if the org.apache.http.legacy has been removed the bootclasspath, false otherwise.
+ */
+ public static boolean removeOAHLFromBCP() {
+ return INSTANCE.mRemovedOAHLFromBCP;
}
- private static boolean isLibraryPresent(ArrayList<String> usesLibraries,
- ArrayList<String> usesOptionalLibraries, String apacheHttpLegacy) {
- return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
- || ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
+ /**
+ * 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) {
+ usesLibraries.add(ANDROID_TEST_MOCK);
+ }
+ if (ArrayUtils.contains(usesOptionalLibraries, ANDROID_TEST_RUNNER)
+ && !androidTestMockPresent) {
+ usesOptionalLibraries.add(ANDROID_TEST_MOCK);
+ }
+
+ pkg.usesLibraries = usesLibraries;
+ pkg.usesOptionalLibraries = usesOptionalLibraries;
+ }
}
- private static @NonNull <T> ArrayList<T> prefix(@Nullable ArrayList<T> cur, T val) {
- if (cur == null) {
- cur = new ArrayList<>();
+ /**
+ * 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";
+
+ @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;
}
}
diff --git a/core/java/android/content/pm/PackageSharedLibraryUpdater.java b/core/java/android/content/pm/PackageSharedLibraryUpdater.java
new file mode 100644
index 000000000000..49d884ca2f34
--- /dev/null
+++ b/core/java/android/content/pm/PackageSharedLibraryUpdater.java
@@ -0,0 +1,55 @@
+/*
+ * 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);
+ }
+}
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 47990a168ab3..60b46b453100 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -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
diff --git a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
index 63a5e4cc1dd8..6996e5056466 100644
--- a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
+++ b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
@@ -73,9 +73,13 @@ public class PackageBackwardCompatibilityTest {
public void targeted_at_O() {
mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertEquals("usesLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesLibraries);
+ if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
+ assertEquals("usesLibraries not updated correctly",
+ arrayList(ORG_APACHE_HTTP_LEGACY),
+ mPackage.usesLibraries);
+ } else {
+ assertNull("usesOptionalLibraries not updated correctly", mPackage.usesLibraries);
+ }
assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
}
@@ -84,10 +88,16 @@ public class PackageBackwardCompatibilityTest {
mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
mPackage.usesLibraries = arrayList(OTHER_LIBRARY);
PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- // The org.apache.http.legacy jar should be added at the start of the list.
- assertEquals("usesLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY, OTHER_LIBRARY),
- mPackage.usesLibraries);
+ if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
+ // The org.apache.http.legacy jar should be added at the start of the list.
+ assertEquals("usesLibraries not updated correctly",
+ arrayList(ORG_APACHE_HTTP_LEGACY, OTHER_LIBRARY),
+ mPackage.usesLibraries);
+ } else {
+ assertEquals("usesLibraries not updated correctly",
+ arrayList(OTHER_LIBRARY),
+ mPackage.usesLibraries);
+ }
assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
}
@@ -96,9 +106,13 @@ public class PackageBackwardCompatibilityTest {
mPackage.applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
mPackage.usesLibraries = arrayList(ORG_APACHE_HTTP_LEGACY);
PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertEquals("usesLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesLibraries);
+ if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
+ assertEquals("usesLibraries not updated correctly",
+ arrayList(ORG_APACHE_HTTP_LEGACY),
+ mPackage.usesLibraries);
+ } else {
+ assertNull("usesLibraries not updated correctly", mPackage.usesLibraries);
+ }
assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
}
@@ -108,18 +122,27 @@ public class PackageBackwardCompatibilityTest {
mPackage.usesOptionalLibraries = arrayList(ORG_APACHE_HTTP_LEGACY);
PackageBackwardCompatibility.modifySharedLibraries(mPackage);
assertNull("usesLibraries not updated correctly", mPackage.usesLibraries);
- assertEquals("usesOptionalLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesOptionalLibraries);
+ if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
+ assertEquals("usesOptionalLibraries not updated correctly",
+ arrayList(ORG_APACHE_HTTP_LEGACY),
+ mPackage.usesOptionalLibraries);
+ } else {
+ assertNull("usesOptionalLibraries not updated correctly",
+ mPackage.usesOptionalLibraries);
+ }
}
@Test
public void org_apache_http_legacy_in_usesLibraries() {
mPackage.usesLibraries = arrayList(ORG_APACHE_HTTP_LEGACY);
PackageBackwardCompatibility.modifySharedLibraries(mPackage);
- assertEquals("usesLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesLibraries);
+ if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
+ assertEquals("usesLibraries not updated correctly",
+ arrayList(ORG_APACHE_HTTP_LEGACY),
+ mPackage.usesLibraries);
+ } else {
+ assertNull("usesLibraries not updated correctly", mPackage.usesLibraries);
+ }
assertNull("usesOptionalLibraries not updated correctly", mPackage.usesOptionalLibraries);
}
@@ -128,9 +151,14 @@ public class PackageBackwardCompatibilityTest {
mPackage.usesOptionalLibraries = arrayList(ORG_APACHE_HTTP_LEGACY);
PackageBackwardCompatibility.modifySharedLibraries(mPackage);
assertNull("usesLibraries not updated correctly", mPackage.usesLibraries);
- assertEquals("usesOptionalLibraries not updated correctly",
- arrayList(ORG_APACHE_HTTP_LEGACY),
- mPackage.usesOptionalLibraries);
+ if (PackageBackwardCompatibility.removeOAHLFromBCP()) {
+ assertEquals("usesOptionalLibraries not updated correctly",
+ arrayList(ORG_APACHE_HTTP_LEGACY),
+ mPackage.usesOptionalLibraries);
+ } else {
+ assertNull("usesOptionalLibraries not updated correctly",
+ mPackage.usesOptionalLibraries);
+ }
}
@Test