Conditionally remove android.test.base from bootclasspath

This makes the runtime handling of the android.test.base library
conditional based on a build flag REMOVE_ATB_FROM_BCP.

When REMOVE_ATB_FROM_BCP=true:
* The framework-atb-backward-compatibility is added to the
  bootclasspath instead of android.test.base.
* Any APK that targets pre-P (or has a dependency on android.test.runner)
  has android.test.base added to their library list.

Otherwise:
* The android.test.base library is added to the bootclasspath.
* Any APK that explicitly specifies that it depends on the
  android.test.base library has the library removed as the classes
  are available at runtime.

Added android.test.base to platform libraries so it can be used when
not on the bootclasspath.

Tested both cases by building with or without the build flag, flashing,
setting up, adding an account, adding a trusted place.

Also, tested that all combinations of REMOVE_ATB_FROM_BCP and
REMOVE_OAHL_FROM_BCP work.

adb install -r -g out/target/product/marlin/testcases/FrameworksCoreTests/FrameworksCoreTests.apk
adb shell am instrument -w -e class android.content.pm.PackageBackwardCompatibilityTest,android.content.pm.AndroidTestRunnerSplitUpdaterTest,android.content.pm.OrgApacheHttpLegacyUpdaterTest,android.content.pm.RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest,android.content.pm.RemoveUnnecessaryAndroidTestBaseLibraryTest,android.content.pm.AndroidTestBaseUpdaterTest com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner

Bug: 30188076
Test: as above
Change-Id: I4b9d8a5bed6787cd334c2b13a458bbc0efc3f3b6
This commit is contained in:
Paul Duffin 2018-01-25 09:58:32 +00:00
parent 43c8446594
commit a3b692113c
10 changed files with 401 additions and 6 deletions

View File

@ -645,8 +645,10 @@ java_library {
],
},
// See comment on framework-oahl-backward-compatibility module below
exclude_srcs: [
// See comment on framework-atb-backward-compatibility module below
"core/java/android/content/pm/AndroidTestBaseUpdater.java",
// See comment on framework-oahl-backward-compatibility module below
"core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java",
],
@ -699,6 +701,18 @@ java_library {
],
}
// A temporary build target that is conditionally included on the bootclasspath if
// android.test.base library has been removed and which provides support for
// maintaining backwards compatibility for APKs that target pre-P and depend on
// android.test.base classes. This is used iff REMOVE_ATB_FROM_BCP=true is
// specified on the build command line.
java_library {
name: "framework-atb-backward-compatibility",
srcs: [
"core/java/android/content/pm/AndroidTestBaseUpdater.java",
],
}
genrule {
name: "framework-statslog-gen",
tools: ["stats-log-api-gen"],

View File

@ -0,0 +1,54 @@
/*
* 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 static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
import android.content.pm.PackageParser.Package;
import com.android.internal.annotations.VisibleForTesting;
/**
* Updates a package to ensure that if it targets < P that the android.test.base library is
* included by default.
*
* <p>This is separated out so that it can be conditionally included at build time depending on
* whether android.test.base is on the bootclasspath or not. In order to include this at
* build time, and remove android.test.base from the bootclasspath pass
* REMOVE_ATB_FROM_BCP=true on the build command line, otherwise this class will not be included
* and the
*
* @hide
*/
@VisibleForTesting
public class AndroidTestBaseUpdater extends PackageSharedLibraryUpdater {
@Override
public void updatePackage(Package pkg) {
// Packages targeted at <= O_MR1 expect the classes in the android.test.base library
// to be accessible so this maintains backward compatibility by adding the
// android.test.base library to those packages.
if (apkTargetsApiLevelLessThanOrEqualToOMR1(pkg)) {
prefixRequiredLibrary(pkg, ANDROID_TEST_BASE);
} else {
// If a package already depends on android.test.runner then add a dependency on
// android.test.base because android.test.runner depends on classes from the
// android.test.base library.
prefixImplicitDependency(pkg, ANDROID_TEST_RUNNER, ANDROID_TEST_BASE);
}
}
}

View File

@ -16,6 +16,7 @@
package android.content.pm;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
@ -52,12 +53,22 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {
"android.content.pm.OrgApacheHttpLegacyUpdater",
RemoveUnnecessaryOrgApacheHttpLegacyLibrary::new);
// Add this before adding AndroidTestBaseUpdater so that android.test.base comes before
// android.test.mock.
packageUpdaters.add(new AndroidTestRunnerSplitUpdater());
// Attempt to load and add the optional updater that will only be available when
// REMOVE_ATB_FROM_BCP=true. If that could not be found then add the default 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.
boolean bootClassPathContainsATB = !addOptionalUpdater(packageUpdaters,
"android.content.pm.AndroidTestBaseUpdater",
RemoveUnnecessaryAndroidTestBaseLibrary::new);
PackageSharedLibraryUpdater[] updaterArray = packageUpdaters
.toArray(new PackageSharedLibraryUpdater[0]);
INSTANCE = new PackageBackwardCompatibility(
bootClassPathContainsOAHL, updaterArray);
bootClassPathContainsOAHL, bootClassPathContainsATB, updaterArray);
}
/**
@ -105,11 +116,14 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {
private final boolean mBootClassPathContainsOAHL;
private final boolean mBootClassPathContainsATB;
private final PackageSharedLibraryUpdater[] mPackageUpdaters;
public PackageBackwardCompatibility(boolean bootClassPathContainsOAHL,
PackageSharedLibraryUpdater[] packageUpdaters) {
boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters) {
this.mBootClassPathContainsOAHL = bootClassPathContainsOAHL;
this.mBootClassPathContainsATB = bootClassPathContainsATB;
this.mPackageUpdaters = packageUpdaters;
}
@ -139,6 +153,14 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {
return INSTANCE.mBootClassPathContainsOAHL;
}
/**
* True if the android.test.base is on the bootclasspath, false otherwise.
*/
@VisibleForTesting
public static boolean bootClassPathContainsATB() {
return INSTANCE.mBootClassPathContainsATB;
}
/**
* Add android.test.mock dependency for any APK that depends on android.test.runner.
*
@ -173,4 +195,18 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {
}
}
/**
* Remove any usages of android.test.base from the shared library as the library is on the
* bootclasspath.
*/
@VisibleForTesting
public static class RemoveUnnecessaryAndroidTestBaseLibrary
extends PackageSharedLibraryUpdater {
@Override
public void updatePackage(Package pkg) {
removeLibrary(pkg, ANDROID_TEST_BASE);
}
}
}

View File

@ -22,6 +22,8 @@ package android.content.pm;
*/
public class SharedLibraryNames {
static final String ANDROID_TEST_BASE = "android.test.base";
static final String ANDROID_TEST_MOCK = "android.test.mock";
static final String ANDROID_TEST_RUNNER = "android.test.runner";

View File

@ -53,6 +53,7 @@ LOCAL_JAVA_LIBRARIES := \
android.test.base \
android.test.mock \
framework-oahl-backward-compatibility \
framework-atb-backward-compatibility \
LOCAL_PACKAGE_NAME := FrameworksCoreTests
LOCAL_COMPATIBILITY_SUITE := device-tests

View File

@ -0,0 +1,108 @@
/*
* 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 static android.content.pm.PackageBuilder.builder;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
import android.os.Build;
import android.support.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Test for {@link AndroidTestBaseUpdater}
*/
@SmallTest
@RunWith(OptionalClassRunner.class)
@OptionalClassRunner.OptionalClass("android.content.pm.AndroidTestBaseUpdater")
public class AndroidTestBaseUpdaterTest extends PackageSharedLibraryUpdaterTest {
private static final String OTHER_LIBRARY = "other.library";
@Test
public void targeted_at_O() {
PackageBuilder before = builder()
.targetSdkVersion(Build.VERSION_CODES.O);
// Should add org.apache.http.legacy.
PackageBuilder after = builder()
.targetSdkVersion(Build.VERSION_CODES.O)
.requiredLibraries(ANDROID_TEST_BASE);
checkBackwardsCompatibility(before, after);
}
@Test
public void targeted_at_O_not_empty_usesLibraries() {
PackageBuilder before = builder()
.targetSdkVersion(Build.VERSION_CODES.O)
.requiredLibraries(OTHER_LIBRARY);
// The org.apache.http.legacy jar should be added at the start of the list because it
// is not on the bootclasspath and the package targets pre-P.
PackageBuilder after = builder()
.targetSdkVersion(Build.VERSION_CODES.O)
.requiredLibraries(ANDROID_TEST_BASE, OTHER_LIBRARY);
checkBackwardsCompatibility(before, after);
}
@Test
public void targeted_at_O_in_usesLibraries() {
PackageBuilder before = builder()
.targetSdkVersion(Build.VERSION_CODES.O)
.requiredLibraries(ANDROID_TEST_BASE);
// No change is required because although org.apache.http.legacy has been removed from
// the bootclasspath the package explicitly requests it.
checkBackwardsCompatibility(before, before);
}
@Test
public void targeted_at_O_in_usesOptionalLibraries() {
PackageBuilder before = builder()
.targetSdkVersion(Build.VERSION_CODES.O)
.optionalLibraries(ANDROID_TEST_BASE);
// No change is required because although org.apache.http.legacy has been removed from
// the bootclasspath the package explicitly requests it.
checkBackwardsCompatibility(before, before);
}
@Test
public void in_usesLibraries() {
PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_BASE);
// No change is required because the package explicitly requests org.apache.http.legacy
// and is targeted at the current version so does not need backwards compatibility.
checkBackwardsCompatibility(before, before);
}
@Test
public void in_usesOptionalLibraries() {
PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_BASE);
// No change is required because the package explicitly requests org.apache.http.legacy
// and is targeted at the current version so does not need backwards compatibility.
checkBackwardsCompatibility(before, before);
}
private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
checkBackwardsCompatibility(before, after, AndroidTestBaseUpdater::new);
}
}

View File

@ -38,7 +38,7 @@ public class AndroidTestRunnerSplitUpdaterTest extends PackageSharedLibraryUpdat
PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_RUNNER);
PackageBuilder after = builder()
.optionalLibraries(ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK);
.optionalLibraries(ANDROID_TEST_MOCK, ANDROID_TEST_RUNNER);
checkBackwardsCompatibility(before, after);
}

View File

@ -17,10 +17,12 @@
package android.content.pm;
import static android.content.pm.PackageBuilder.builder;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
import android.os.Build;
import android.support.test.filters.SmallTest;
@ -55,9 +57,20 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate
Assume.assumeTrue(PackageBackwardCompatibility.bootClassPathContainsOAHL());
}
/**
* Detect when the android.test.base is not on the bootclasspath.
*
* <p>This test will be ignored when org.apache.http.legacy is not on the bootclasspath and
* succeed otherwise. This allows a developer to ensure that the tests are being
*/
@Test
public void detectWhenATBisOnBCP() {
Assume.assumeTrue(PackageBackwardCompatibility.bootClassPathContainsATB());
}
/**
* Ensures that the {@link PackageBackwardCompatibility} uses {@link OrgApacheHttpLegacyUpdater}
* when necessary.
* and {@link AndroidTestBaseUpdater} when necessary.
*
* <p>More comprehensive tests for that class can be found in
* {@link OrgApacheHttpLegacyUpdaterTest}.
@ -68,6 +81,9 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate
.targetSdkVersion(Build.VERSION_CODES.O);
List<String> expected = new ArrayList<>();
if (!PackageBackwardCompatibility.bootClassPathContainsATB()) {
expected.add(ANDROID_TEST_BASE);
}
if (!PackageBackwardCompatibility.bootClassPathContainsOAHL()) {
expected.add(ORG_APACHE_HTTP_LEGACY);
}
@ -103,6 +119,30 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate
checkBackwardsCompatibility(before, after);
}
/**
* Ensures that the {@link PackageBackwardCompatibility} uses
* {@link RemoveUnnecessaryAndroidTestBaseLibrary}
* when necessary.
*
* <p>More comprehensive tests for that class can be found in
* {@link RemoveUnnecessaryAndroidTestBaseLibraryTest}.
*/
@Test
public void android_test_base_in_usesLibraries() {
Assume.assumeTrue("Test requires that "
+ ANDROID_TEST_BASE + " is on the bootclasspath",
PackageBackwardCompatibility.bootClassPathContainsATB());
PackageBuilder before = builder()
.requiredLibraries(ANDROID_TEST_BASE);
// android.test.base should be removed from the libraries because it is provided
// on the bootclasspath and providing both increases start up cost unnecessarily.
PackageBuilder after = builder();
checkBackwardsCompatibility(before, after);
}
/**
* Ensures that the {@link PackageBackwardCompatibility} uses a
* {@link PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater}.
@ -114,8 +154,15 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate
public void android_test_runner_in_usesLibraries() {
PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_RUNNER);
List<String> expected = new ArrayList<>();
if (!PackageBackwardCompatibility.bootClassPathContainsATB()) {
expected.add(ANDROID_TEST_BASE);
}
expected.add(ANDROID_TEST_MOCK);
expected.add(ANDROID_TEST_RUNNER);
PackageBuilder after = builder()
.requiredLibraries(ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK);
.requiredLibraries(expected);
checkBackwardsCompatibility(before, after);
}

View File

@ -0,0 +1,131 @@
/*
* 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 static android.content.pm.PackageBuilder.builder;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
import android.os.Build;
import android.support.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
* Test for {@link RemoveUnnecessaryAndroidTestBaseLibrary}
*/
@SmallTest
@RunWith(JUnit4.class)
public class RemoveUnnecessaryAndroidTestBaseLibraryTest
extends PackageSharedLibraryUpdaterTest {
private static final String OTHER_LIBRARY = "other.library";
@Test
public void targeted_at_O() {
PackageBuilder before = builder()
.targetSdkVersion(Build.VERSION_CODES.O);
// No change required.
checkBackwardsCompatibility(before, before);
}
@Test
public void targeted_at_O_not_empty_usesLibraries() {
PackageBuilder before = builder()
.targetSdkVersion(Build.VERSION_CODES.O)
.requiredLibraries(OTHER_LIBRARY);
// No change required.
checkBackwardsCompatibility(before, before);
}
@Test
public void targeted_at_O_in_usesLibraries() {
PackageBuilder before = builder()
.targetSdkVersion(Build.VERSION_CODES.O)
.requiredLibraries(ANDROID_TEST_BASE);
// android.test.base should be removed from the libraries because it is provided
// on the bootclasspath and providing both increases start up cost unnecessarily.
PackageBuilder after = builder()
.targetSdkVersion(Build.VERSION_CODES.O);
checkBackwardsCompatibility(before, after);
}
@Test
public void targeted_at_O_in_usesOptionalLibraries() {
PackageBuilder before = builder()
.targetSdkVersion(Build.VERSION_CODES.O)
.optionalLibraries(ANDROID_TEST_BASE);
// android.test.base should be removed from the libraries because it is provided
// on the bootclasspath and providing both increases start up cost unnecessarily.
PackageBuilder after = builder()
.targetSdkVersion(Build.VERSION_CODES.O);
checkBackwardsCompatibility(before, after);
}
@Test
public void in_usesLibraries() {
PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_BASE);
// android.test.base should be removed from the libraries because it is provided
// on the bootclasspath and providing both increases start up cost unnecessarily.
PackageBuilder after = builder();
checkBackwardsCompatibility(before, after);
}
@Test
public void in_usesOptionalLibraries() {
PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_BASE);
// android.test.base should be removed from the libraries because it is provided
// on the bootclasspath and providing both increases start up cost unnecessarily.
PackageBuilder after = builder();
checkBackwardsCompatibility(before, after);
}
@Test
public void in_bothLibraries() {
PackageBuilder before = builder()
.requiredLibraries(ANDROID_TEST_BASE)
.optionalLibraries(ANDROID_TEST_BASE);
// android.test.base should be removed from the libraries because it is provided
// on the bootclasspath and providing both increases start up cost unnecessarily.
PackageBuilder after = builder();
checkBackwardsCompatibility(before, after);
}
private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
// TODO(b/72538146) - Cannot use constructor reference here because it is also used in
// PackageBackwardCompatibility and that seems to create a package-private lambda in
// android.content.pm which this then tries to reuse but fails because it cannot access
// package-private classes/members because the test is loaded by a different ClassLoader
// than the lambda.
checkBackwardsCompatibility(before, after,
() -> new RemoveUnnecessaryAndroidTestBaseLibrary());
}
}

View File

@ -179,6 +179,8 @@
<!-- This is a list of all the libraries available for application
code to link against. -->
<library name="android.test.base"
file="/system/framework/android.test.base.jar" />
<library name="android.test.mock"
file="/system/framework/android.test.mock.jar" />
<library name="android.test.runner"