Merge AOSP trunk
Bug: 262638121 Merged-In: I4127e843cf1caf460a1c6b949a97ef3418ff895c Change-Id: Ic6c35a46bb462f904e8e2802853715cc57c92729
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
android.hardware.audio.common-V1-ndk(minSdkVersion:31)
|
||||
android.hardware.audio.common@5.0(minSdkVersion:30)
|
||||
android.hardware.bluetooth-V1-ndk(minSdkVersion:33)
|
||||
android.hardware.bluetooth.a2dp@1.0(minSdkVersion:30)
|
||||
android.hardware.bluetooth.audio-V1-ndk(minSdkVersion:31)
|
||||
android.hardware.bluetooth.audio-V2-ndk(minSdkVersion:31)
|
||||
@@ -63,6 +64,7 @@ android.hardware.neuralnetworks@1.1(minSdkVersion:30)
|
||||
android.hardware.neuralnetworks@1.2(minSdkVersion:30)
|
||||
android.hardware.neuralnetworks@1.3(minSdkVersion:30)
|
||||
android.hardware.radio-V1.0-java(minSdkVersion:current)
|
||||
android.hardware.radio.sap-V1-java(minSdkVersion:33)
|
||||
android.hardware.security.rkp-V3-java(minSdkVersion:33)
|
||||
android.hardware.tetheroffload.config-V1.0-java(minSdkVersion:current)
|
||||
android.hardware.tetheroffload.control-V1.0-java(minSdkVersion:current)
|
||||
@@ -130,6 +132,7 @@ androidx.collection_collection(minSdkVersion:24)
|
||||
androidx.collection_collection-jvm(minSdkVersion:24)
|
||||
androidx.collection_collection-ktx(minSdkVersion:24)
|
||||
androidx.concurrent_concurrent-futures(minSdkVersion:24)
|
||||
androidx.constraintlayout_constraintlayout-core(minSdkVersion:24)
|
||||
androidx.coordinatorlayout_coordinatorlayout(minSdkVersion:14)
|
||||
androidx.core_core(minSdkVersion:14)
|
||||
androidx.core_core-ktx(minSdkVersion:14)
|
||||
@@ -544,6 +547,8 @@ libhidlmemory(minSdkVersion:29)
|
||||
libhwbinder-impl-internal(minSdkVersion:29)
|
||||
libhwbinder_headers(minSdkVersion:29)
|
||||
libidna(minSdkVersion:29)
|
||||
libimapper_providerutils(minSdkVersion:29)
|
||||
libimapper_stablec(minSdkVersion:29)
|
||||
libion(minSdkVersion:29)
|
||||
libip_checksum(minSdkVersion:30)
|
||||
libjni(minSdkVersion:29)
|
||||
@@ -747,7 +752,9 @@ libunwindstack(minSdkVersion:29)
|
||||
liburl(minSdkVersion:29)
|
||||
libutf(minSdkVersion:(no version))
|
||||
libutf(minSdkVersion:14)
|
||||
libutils(minSdkVersion:29)
|
||||
libutils(minSdkVersion:apex_inherit)
|
||||
libutils_headers(minSdkVersion:29)
|
||||
libutils_headers(minSdkVersion:apex_inherit)
|
||||
libuwb_uci_packets(minSdkVersion:Tiramisu)
|
||||
libvorbisidec(minSdkVersion:29)
|
||||
@@ -839,6 +846,7 @@ networkstack-aidl-interfaces-V12-java(minSdkVersion:29)
|
||||
networkstack-aidl-interfaces-V13-java(minSdkVersion:29)
|
||||
networkstack-aidl-interfaces-V14-java(minSdkVersion:29)
|
||||
networkstack-aidl-interfaces-V15-java(minSdkVersion:29)
|
||||
networkstack-aidl-interfaces-V16-java(minSdkVersion:29)
|
||||
networkstack-aidl-latest(minSdkVersion:29)
|
||||
networkstack-client(minSdkVersion:29)
|
||||
NetworkStackApi29Shims(minSdkVersion:29)
|
||||
@@ -864,6 +872,11 @@ note_memtag_heap_async(minSdkVersion:16)
|
||||
note_memtag_heap_sync(minSdkVersion:16)
|
||||
offlinelocationtimezoneprovider(minSdkVersion:31)
|
||||
okhttp(minSdkVersion:31)
|
||||
okio-lib(minSdkVersion:30)
|
||||
opencensus-java-api(minSdkVersion:33)
|
||||
opencensus-java-api(minSdkVersion:current)
|
||||
opencensus-java-contrib-grpc-metrics(minSdkVersion:33)
|
||||
opencensus-java-contrib-grpc-metrics(minSdkVersion:current)
|
||||
OsuLoginGoogle(minSdkVersion:30)
|
||||
perfetto_trace_protos(minSdkVersion:S)
|
||||
PermissionController(minSdkVersion:28)
|
||||
@@ -911,6 +924,7 @@ prebuilt_androidx.collection_collection-nodeps(minSdkVersion:24)
|
||||
prebuilt_androidx.collection_collection-nodeps(minSdkVersion:30)
|
||||
prebuilt_androidx.collection_collection-nodeps(minSdkVersion:current)
|
||||
prebuilt_androidx.concurrent_concurrent-futures-nodeps(minSdkVersion:24)
|
||||
prebuilt_androidx.constraintlayout_constraintlayout-core-nodeps(minSdkVersion:24)
|
||||
prebuilt_androidx.coordinatorlayout_coordinatorlayout-nodeps(minSdkVersion:(no version))
|
||||
prebuilt_androidx.coordinatorlayout_coordinatorlayout-nodeps(minSdkVersion:14)
|
||||
prebuilt_androidx.core_core-ktx-nodeps(minSdkVersion:(no version))
|
||||
|
||||
@@ -24,4 +24,12 @@ java_library_host {
|
||||
"compatibility-host-util",
|
||||
"androidx.annotation_annotation",
|
||||
],
|
||||
static_libs: [
|
||||
"compat-classpaths-testing",
|
||||
"classpath_classes_proto_java"
|
||||
],
|
||||
visibility: [
|
||||
"//packages/modules/common:__subpackages__",
|
||||
"//packages/modules/SdkExtensions",
|
||||
],
|
||||
}
|
||||
@@ -16,19 +16,37 @@
|
||||
|
||||
package com.android.modules.targetprep;
|
||||
|
||||
import static android.compat.testing.Classpaths.ClasspathType.BOOTCLASSPATH;
|
||||
import static android.compat.testing.Classpaths.ClasspathType.SYSTEMSERVERCLASSPATH;
|
||||
|
||||
import android.compat.testing.Classpaths;
|
||||
import android.compat.testing.Classpaths.ClasspathType;
|
||||
|
||||
import com.android.modules.proto.ClasspathClasses.Classpath;
|
||||
import com.android.modules.proto.ClasspathClasses.ClasspathClassesDump;
|
||||
import com.android.modules.proto.ClasspathClasses.ClasspathEntry;
|
||||
import com.android.modules.proto.ClasspathClasses.Jar;
|
||||
|
||||
import com.android.tradefed.config.Option;
|
||||
import com.android.tradefed.device.DeviceNotAvailableException;
|
||||
import com.android.tradefed.device.INativeDevice;
|
||||
import com.android.tradefed.device.ITestDevice;
|
||||
import com.android.tradefed.invoker.TestInformation;
|
||||
import com.android.tradefed.log.LogUtil.CLog;
|
||||
import com.android.tradefed.targetprep.BaseTargetPreparer;
|
||||
import com.android.tradefed.targetprep.TargetSetupError;
|
||||
import com.android.tradefed.util.RunUtil;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
|
||||
/*
|
||||
* Target preparer that fetches classpath relevant artifacts for a test in a 'reentrant' manner.
|
||||
@@ -54,20 +72,43 @@ import java.nio.file.Path;
|
||||
public class ClasspathFetcher extends BaseTargetPreparer {
|
||||
|
||||
public static final String DEVICE_JAR_ARTIFACTS_TAG = "device-jar-artifacts";
|
||||
public static final String BCP_CLASSES_FILE = "bcp.pb";
|
||||
public static final String SSCP_CLASSES_FILE = "sscp.pb";
|
||||
|
||||
// TODO(andreionea): also fetch classes for standalone system server jars, apk-in-apex and
|
||||
// shared libraries. They require more mocking on the test side.
|
||||
|
||||
public static final String APEX_PKG_TAG = "apex-package";
|
||||
// Special case for fetching only non-updatable platform.
|
||||
public static final String PLATFORM_PACKAGE = "platform";
|
||||
|
||||
@Option(name = "apex-package",
|
||||
description = "The package name of the apex under test.")
|
||||
private String mApexPackage;
|
||||
|
||||
private boolean mFetchedArtifacts = false;
|
||||
|
||||
@Override
|
||||
public void setUp(TestInformation testInfo)
|
||||
throws TargetSetupError, DeviceNotAvailableException {
|
||||
Objects.requireNonNull(testInfo.getDevice());
|
||||
if (mApexPackage != null) {
|
||||
testInfo.properties().put(APEX_PKG_TAG, mApexPackage);
|
||||
}
|
||||
// The artifacts have been fetched already, no need to do anything else.
|
||||
if (testInfo.properties().containsKey(DEVICE_JAR_ARTIFACTS_TAG)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final Path tmpDir = Files.createTempDirectory("device_artifacts");
|
||||
testInfo.properties().put(DEVICE_JAR_ARTIFACTS_TAG, tmpDir.toAbsolutePath().toString());
|
||||
// TODO(b/254647172): Fetch data
|
||||
testInfo.properties().put(DEVICE_JAR_ARTIFACTS_TAG,
|
||||
tmpDir.toAbsolutePath().toString());
|
||||
|
||||
getClassesInClasspath(testInfo.getDevice(), BOOTCLASSPATH)
|
||||
.writeTo(new FileOutputStream(new File(tmpDir.toFile(), BCP_CLASSES_FILE)));
|
||||
getClassesInClasspath(testInfo.getDevice(), SYSTEMSERVERCLASSPATH)
|
||||
.writeTo(new FileOutputStream(new File(tmpDir.toFile(), SSCP_CLASSES_FILE)));
|
||||
|
||||
mFetchedArtifacts = true;
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException("Could not create temp artifacts dir!", e);
|
||||
@@ -84,13 +125,70 @@ public class ClasspathFetcher extends BaseTargetPreparer {
|
||||
+ " artifacts, but the DEVICE_JAR_ARTIFACTS_TAG property was removed");
|
||||
}
|
||||
final File jarArtifactsDir = new File(path);
|
||||
if (!jarArtifactsDir.delete()) {
|
||||
throw new RuntimeException("Failed to remove jar artifacts dir!");
|
||||
}
|
||||
deleteDirectory(jarArtifactsDir);
|
||||
} finally {
|
||||
testInfo.properties().remove(DEVICE_JAR_ARTIFACTS_TAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Classpath classpathTypeToClasspathEnum(ClasspathType t) {
|
||||
switch(t) {
|
||||
case BOOTCLASSPATH:
|
||||
return Classpath.valueOf(Classpath.BOOTCLASSPATH_VALUE);
|
||||
case SYSTEMSERVERCLASSPATH:
|
||||
return Classpath.valueOf(Classpath.SYSTEMSERVERCLASSPATH_VALUE);
|
||||
default:
|
||||
throw new RuntimeException("Unknown classpath type " + t);
|
||||
}
|
||||
}
|
||||
|
||||
private ImmutableSet<String> getClassesInFile(INativeDevice device, String file)
|
||||
throws DeviceNotAvailableException, IOException {
|
||||
final File jar = device.pullFile(file);
|
||||
if (jar == null) {
|
||||
throw new IllegalStateException("could not pull remote file " + file);
|
||||
}
|
||||
return Classpaths.getClassDefsFromJar(jar)
|
||||
.stream()
|
||||
.map(ClassDef::getType)
|
||||
.collect(ImmutableSet.toImmutableSet());
|
||||
}
|
||||
|
||||
private ClasspathClassesDump getClassesInClasspath(INativeDevice device, ClasspathType type)
|
||||
throws DeviceNotAvailableException, IOException {
|
||||
ClasspathClassesDump.Builder builder = ClasspathClassesDump.newBuilder();
|
||||
final ImmutableList<String> jars = Classpaths.getJarsOnClasspath(device, type);
|
||||
for (String jar : jars) {
|
||||
ClasspathEntry.Builder entryBuilder = ClasspathEntry.newBuilder();
|
||||
Jar.Builder jarBuilder = Jar.newBuilder();
|
||||
jarBuilder.setClasspath(classpathTypeToClasspathEnum(type));
|
||||
jarBuilder.setPath(jar);
|
||||
entryBuilder.setJar(jarBuilder.build());
|
||||
entryBuilder.addAllClasses(getClassesInFile(device, jar));
|
||||
builder.addEntries(entryBuilder.build());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a directory and its contents recursively
|
||||
*
|
||||
* @param directory to delete
|
||||
*/
|
||||
private static void deleteDirectory(File directory) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (!file.isDirectory()) {
|
||||
file.delete();
|
||||
} else {
|
||||
deleteDirectory(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
directory.delete();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
java_test_host {
|
||||
name: "ConformanceFrameworkTests",
|
||||
srcs: ["*.java"],
|
||||
static_libs: [
|
||||
"junit",
|
||||
"ClasspathFetcher",
|
||||
"truth-prebuilt",
|
||||
"objenesis",
|
||||
],
|
||||
libs: [
|
||||
"cts-tradefed",
|
||||
"tradefed",
|
||||
"compatibility-host-util",
|
||||
],
|
||||
test_suites: [
|
||||
"general-tests",
|
||||
],
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 com.android.modules.conformanceframework;
|
||||
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import com.android.modules.proto.ClasspathClasses.ClasspathClassesDump;
|
||||
import com.android.modules.proto.ClasspathClasses.ClasspathEntry;
|
||||
import com.android.modules.proto.ClasspathClasses.Jar;
|
||||
import com.android.modules.targetprep.ClasspathFetcher;
|
||||
import com.android.modules.utils.build.testing.DeviceSdkLevel;
|
||||
import com.android.tradefed.config.Option;
|
||||
import com.android.tradefed.device.DeviceNotAvailableException;
|
||||
import com.android.tradefed.device.ITestDevice;
|
||||
import com.android.tradefed.invoker.TestInformation;
|
||||
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
|
||||
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
|
||||
import com.android.tradefed.testtype.junit4.BeforeClassWithInfo;
|
||||
import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tests for detecting no duplicate class files are present on BOOTCLASSPATH and
|
||||
* SYSTEMSERVERCLASSPATH.
|
||||
*
|
||||
* <p>Duplicate class files are not safe as some of the jars on *CLASSPATH are updated outside of
|
||||
* the main dessert release cycle; they also contribute to unnecessary disk space usage.
|
||||
*/
|
||||
@RunWith(DeviceJUnit4ClassRunner.class)
|
||||
public class DuplicateClassesTest extends BaseHostJUnit4Test {
|
||||
private static ImmutableSet<String> sBootclasspathJars;
|
||||
private static ImmutableSet<String> sSystemserverclasspathJars;
|
||||
|
||||
private static ImmutableMultimap<String, String> sJarsToClasses;
|
||||
private static String sApexPackage;
|
||||
|
||||
private DeviceSdkLevel mDeviceSdkLevel;
|
||||
|
||||
/**
|
||||
* Fetch all classpath info extracted by ClasspathFetcher.
|
||||
*
|
||||
*/
|
||||
@BeforeClassWithInfo
|
||||
public static void setupOnce(TestInformation testInfo) throws Exception {
|
||||
final String dctArtifactsPath = Objects.requireNonNull(
|
||||
testInfo.properties().get(ClasspathFetcher.DEVICE_JAR_ARTIFACTS_TAG));
|
||||
sApexPackage = testInfo.properties().get(ClasspathFetcher.APEX_PKG_TAG);
|
||||
final ImmutableMultimap.Builder<String, String> jarsToClasses =
|
||||
new ImmutableMultimap.Builder<>();
|
||||
final File bcpDumpFile = new File(dctArtifactsPath, ClasspathFetcher.BCP_CLASSES_FILE);
|
||||
final ClasspathClassesDump bcpDump =
|
||||
ClasspathClassesDump.parseFrom(new FileInputStream(bcpDumpFile));
|
||||
sBootclasspathJars = bcpDump.getEntriesList().stream()
|
||||
.map(entry -> entry.getJar().getPath())
|
||||
.collect(ImmutableSet.toImmutableSet());
|
||||
bcpDump.getEntriesList().stream()
|
||||
.forEach(entry -> {
|
||||
jarsToClasses.putAll(entry.getJar().getPath(), entry.getClassesList());
|
||||
});
|
||||
final File sscpDumpFile = new File(dctArtifactsPath, ClasspathFetcher.SSCP_CLASSES_FILE);
|
||||
final ClasspathClassesDump sscpDump =
|
||||
ClasspathClassesDump.parseFrom(new FileInputStream(sscpDumpFile));
|
||||
sSystemserverclasspathJars = sscpDump.getEntriesList().stream()
|
||||
.map(entry -> entry.getJar().getPath())
|
||||
.collect(ImmutableSet.toImmutableSet());
|
||||
sscpDump.getEntriesList().stream()
|
||||
.forEach(entry -> {
|
||||
jarsToClasses.putAll(entry.getJar().getPath(), entry.getClassesList());
|
||||
});
|
||||
sJarsToClasses = jarsToClasses.build();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mDeviceSdkLevel = new DeviceSdkLevel(getDevice());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that there are no duplicate classes among jars listed in BOOTCLASSPATH.
|
||||
*/
|
||||
@Test
|
||||
public void testBootclasspath_nonDuplicateClasses() throws Exception {
|
||||
assumeTrue(mDeviceSdkLevel.isDeviceAtLeastR());
|
||||
assertThat(getDuplicateClasses(sBootclasspathJars)).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that there are no duplicate classes among jars listed in SYSTEMSERVERCLASSPATH.
|
||||
*/
|
||||
@Test
|
||||
public void testSystemserverClasspath_nonDuplicateClasses() throws Exception {
|
||||
assumeTrue(mDeviceSdkLevel.isDeviceAtLeastR());
|
||||
assertThat(getDuplicateClasses(sSystemserverclasspathJars)).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that there are no duplicate classes among jars listed in BOOTCLASSPATH and
|
||||
* SYSTEMSERVERCLASSPATH.
|
||||
*/
|
||||
@Test
|
||||
public void testSystemserverAndBootClasspath_nonDuplicateClasses() throws Exception {
|
||||
assumeTrue(mDeviceSdkLevel.isDeviceAtLeastR());
|
||||
final ImmutableSet.Builder<String> jars = new ImmutableSet.Builder<>();
|
||||
jars.addAll(sBootclasspathJars);
|
||||
jars.addAll(sSystemserverclasspathJars);
|
||||
assertThat(getDuplicateClasses(jars.build())).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the duplicate classes within a list of jar files.
|
||||
*
|
||||
* @param jars a list of jar files.
|
||||
* @return a multimap with the class name as a key and the jar files as a value.
|
||||
*/
|
||||
private Multimap<String, String> getDuplicateClasses(ImmutableCollection<String> jars) {
|
||||
final HashMultimap<String, String> allClasses = HashMultimap.create();
|
||||
Multimaps.invertFrom(Multimaps.filterKeys(sJarsToClasses, jars::contains), allClasses);
|
||||
return Multimaps.filterKeys(allClasses, key -> validDuplicates(allClasses.get(key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Filtering function for excluding invalid / uninteresting duplicates.
|
||||
*
|
||||
* This will filter out classes that are in only 1 jar, or duplicates that
|
||||
* do not include jars in the apex under test.
|
||||
*/
|
||||
|
||||
private boolean validDuplicates(Collection<String> duplicateJars) {
|
||||
if (duplicateJars.size() <= 1) {
|
||||
return false;
|
||||
}
|
||||
if (sApexPackage.equals(ClasspathFetcher.PLATFORM_PACKAGE)) {
|
||||
return duplicateJars.stream()
|
||||
.anyMatch(jar -> !jar.startsWith("/apex"));
|
||||
}
|
||||
final String apexPrefix = "/apex/" + sApexPackage;
|
||||
return duplicateJars.stream()
|
||||
.anyMatch(jar -> jar.startsWith(apexPrefix));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,10 @@ java_test_host {
|
||||
"junit",
|
||||
"tradefed",
|
||||
],
|
||||
java_resources: [
|
||||
":LibraryA",
|
||||
":LibraryB",
|
||||
],
|
||||
test_suites: [
|
||||
"general-tests",
|
||||
],
|
||||
|
||||
@@ -22,17 +22,30 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
import com.android.modules.proto.ClasspathClasses.ClasspathClassesDump;
|
||||
import com.android.modules.proto.ClasspathClasses.ClasspathEntry;
|
||||
import com.android.tradefed.build.IDeviceBuildInfo;
|
||||
import com.android.tradefed.device.ITestDevice;
|
||||
import com.android.tradefed.invoker.IInvocationContext;
|
||||
import com.android.tradefed.invoker.InvocationContext;
|
||||
import com.android.tradefed.invoker.TestInformation;
|
||||
import com.android.tradefed.util.CommandResult;
|
||||
import com.android.tradefed.util.CommandStatus;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@@ -46,6 +59,7 @@ import org.junit.runners.JUnit4;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class ClasspathFetcherTest {
|
||||
@@ -57,6 +71,9 @@ public class ClasspathFetcherTest {
|
||||
|
||||
private TestInformation mTestInfo;
|
||||
|
||||
private String mBootclasspathJarNames = "";
|
||||
private String mSystemServerclasspathJarNames = "";
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
@@ -64,6 +81,28 @@ public class ClasspathFetcherTest {
|
||||
when(mMockTestDevice.getSerialNumber()).thenReturn(SERIAL);
|
||||
when(mMockTestDevice.getDeviceDescriptor()).thenReturn(null);
|
||||
when(mMockTestDevice.isAppEnumerationSupported()).thenReturn(false);
|
||||
when(mMockTestDevice.executeShellV2Command(eq("echo $BOOTCLASSPATH"))).then(
|
||||
invocation -> {
|
||||
return successfulCommandResult(mBootclasspathJarNames, "");
|
||||
}
|
||||
);
|
||||
when(mMockTestDevice.executeShellV2Command(eq("echo $SYSTEMSERVERCLASSPATH"))).then(
|
||||
invocation -> {
|
||||
return successfulCommandResult(mSystemServerclasspathJarNames, "");
|
||||
}
|
||||
);
|
||||
when(mMockTestDevice.pullFile(anyString())).then(
|
||||
invocation -> {
|
||||
final String path = invocation.getArgument(0);
|
||||
final File tempFile = File.createTempFile(path, null);
|
||||
|
||||
try (InputStream is =
|
||||
ClasspathFetcherTest.class.getClassLoader().getResourceAsStream(path)) {
|
||||
Files.copy(is, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
return tempFile;
|
||||
}
|
||||
);
|
||||
IInvocationContext context = new InvocationContext();
|
||||
context.addAllocatedDevice("device", mMockTestDevice);
|
||||
context.addDeviceBuildInfo("device", mMockBuildInfo);
|
||||
@@ -72,6 +111,8 @@ public class ClasspathFetcherTest {
|
||||
|
||||
@Test
|
||||
public void testSingleArtifactFetcher() throws Exception {
|
||||
mBootclasspathJarNames = "LibraryA.jar";
|
||||
mSystemServerclasspathJarNames = "LibraryB.jar";
|
||||
final ClasspathFetcher fetcher = new ClasspathFetcher();
|
||||
fetcher.setUp(mTestInfo);
|
||||
assertThat(mTestInfo.properties().containsKey(DEVICE_JAR_ARTIFACTS_TAG)).isTrue();
|
||||
@@ -81,6 +122,8 @@ public class ClasspathFetcherTest {
|
||||
|
||||
@Test
|
||||
public void testMultipleArtifactFetchers() throws Exception {
|
||||
mBootclasspathJarNames = "LibraryA.jar";
|
||||
mSystemServerclasspathJarNames = "LibraryB.jar";
|
||||
final ClasspathFetcher fetcher1 = new ClasspathFetcher();
|
||||
final ClasspathFetcher fetcher2 = new ClasspathFetcher();
|
||||
|
||||
@@ -92,4 +135,68 @@ public class ClasspathFetcherTest {
|
||||
fetcher1.tearDown(mTestInfo, null);
|
||||
assertThat(mTestInfo.properties().containsKey(DEVICE_JAR_ARTIFACTS_TAG)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchCorrectBcpClasses() throws Exception {
|
||||
mBootclasspathJarNames = "LibraryA.jar";
|
||||
mSystemServerclasspathJarNames = "LibraryB.jar";
|
||||
final ClasspathFetcher fetcher = new ClasspathFetcher();
|
||||
|
||||
try {
|
||||
fetcher.setUp(mTestInfo);
|
||||
|
||||
final File bcpProto = new File(mTestInfo.properties().get(DEVICE_JAR_ARTIFACTS_TAG),
|
||||
ClasspathFetcher.BCP_CLASSES_FILE);
|
||||
assertThat(bcpProto.exists()).isTrue();
|
||||
ClasspathClassesDump dump =
|
||||
ClasspathClassesDump.parseFrom(new FileInputStream(bcpProto));
|
||||
List<ClasspathEntry> entries = dump.getEntriesList();
|
||||
assertThat(entries.size()).isEqualTo(1);
|
||||
ClasspathEntry entry = entries.get(0);
|
||||
assertThat(entry.hasJar()).isTrue();
|
||||
assertThat(entry.getJar().getPath()).isEqualTo("LibraryA.jar");
|
||||
assertThat(entry.getClassesList().size()).isEqualTo(1);
|
||||
assertThat(entry.getClassesList().get(0))
|
||||
.isEqualTo("Lcom/android/modules/targetprep/android/A;");
|
||||
} finally {
|
||||
fetcher.tearDown(mTestInfo, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchCorrectSscpClasses() throws Exception {
|
||||
mBootclasspathJarNames = "LibraryA.jar";
|
||||
mSystemServerclasspathJarNames = "LibraryB.jar";
|
||||
final ClasspathFetcher fetcher = new ClasspathFetcher();
|
||||
|
||||
try {
|
||||
fetcher.setUp(mTestInfo);
|
||||
|
||||
final File sscpProto = new File(mTestInfo.properties().get(DEVICE_JAR_ARTIFACTS_TAG),
|
||||
ClasspathFetcher.SSCP_CLASSES_FILE);
|
||||
assertThat(sscpProto.exists()).isTrue();
|
||||
ClasspathClassesDump dump =
|
||||
ClasspathClassesDump.parseFrom(new FileInputStream(sscpProto));
|
||||
List<ClasspathEntry> entries = dump.getEntriesList();
|
||||
assertThat(entries.size()).isEqualTo(1);
|
||||
ClasspathEntry entry = entries.get(0);
|
||||
assertThat(entry.hasJar()).isTrue();
|
||||
assertThat(entry.getJar().getPath()).isEqualTo("LibraryB.jar");
|
||||
assertThat(entry.getClassesList().size()).isEqualTo(1);
|
||||
assertThat(entry.getClassesList().get(0))
|
||||
.isEqualTo("Lcom/android/modules/targetprep/android/B;");
|
||||
} finally {
|
||||
fetcher.tearDown(mTestInfo, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static CommandResult successfulCommandResult(String stdout, String stderr) {
|
||||
final CommandResult result = new CommandResult();
|
||||
result.setStatus(CommandStatus.SUCCESS);
|
||||
result.setExitCode(0);
|
||||
result.setStdout(stdout);
|
||||
result.setStderr(stderr);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
3
javatests/com/android/modules/targetprep/android/A.java
Normal file
3
javatests/com/android/modules/targetprep/android/A.java
Normal file
@@ -0,0 +1,3 @@
|
||||
package com.android.modules.targetprep.android;
|
||||
|
||||
public class A {}
|
||||
31
javatests/com/android/modules/targetprep/android/Android.bp
Normal file
31
javatests/com/android/modules/targetprep/android/Android.bp
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "LibraryA",
|
||||
srcs: ["A.java"],
|
||||
installable: true,
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "LibraryB",
|
||||
srcs: ["B.java"],
|
||||
installable: true,
|
||||
}
|
||||
3
javatests/com/android/modules/targetprep/android/B.java
Normal file
3
javatests/com/android/modules/targetprep/android/B.java
Normal file
@@ -0,0 +1,3 @@
|
||||
package com.android.modules.targetprep.android;
|
||||
|
||||
public class B {}
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
default_visibility: ["//packages/modules/common/javatests:__subpackages__"],
|
||||
}
|
||||
|
||||
android_test_helper_app {
|
||||
@@ -25,5 +26,6 @@ android_test_helper_app {
|
||||
"truth-prebuilt",
|
||||
],
|
||||
sdk_version: "current",
|
||||
min_sdk_version: "31",
|
||||
target_sdk_version: "31",
|
||||
}
|
||||
|
||||
@@ -25,5 +25,6 @@ android_test_helper_app {
|
||||
"truth-prebuilt",
|
||||
],
|
||||
sdk_version: "current",
|
||||
min_sdk_version: "Tiramisu",
|
||||
target_sdk_version: "Tiramisu",
|
||||
}
|
||||
|
||||
@@ -29,5 +29,6 @@ android_test_helper_app {
|
||||
"androidx.test.core",
|
||||
],
|
||||
sdk_version: "current",
|
||||
min_sdk_version: "Tiramisu",
|
||||
target_sdk_version: "Tiramisu",
|
||||
}
|
||||
|
||||
@@ -240,7 +240,10 @@ DCLA_MIN_SDK_VERSION = "31"
|
||||
|
||||
soong_config_module_type_import {
|
||||
from: "system/apex/Android.bp",
|
||||
module_types: ["library_linking_strategy_apex_defaults"],
|
||||
module_types: [
|
||||
"library_linking_strategy_apex_defaults",
|
||||
"library_linking_strategy_cc_defaults",
|
||||
],
|
||||
}
|
||||
|
||||
library_linking_strategy_apex_defaults {
|
||||
@@ -322,3 +325,20 @@ apex_defaults {
|
||||
compressible: true,
|
||||
defaults_visibility: ["//packages/modules:__subpackages__"],
|
||||
}
|
||||
|
||||
APEX_LOWEST_MIN_SDK_VERSION = "29"
|
||||
|
||||
library_linking_strategy_cc_defaults {
|
||||
name: "apex-lowest-min-sdk-version",
|
||||
defaults_visibility: [
|
||||
"//system/core/libutils",
|
||||
],
|
||||
min_sdk_version: APEX_LOWEST_MIN_SDK_VERSION,
|
||||
soong_config_variables: {
|
||||
library_linking_strategy: {
|
||||
prefer_static: {
|
||||
min_sdk_version: "apex_inherit",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -57,7 +57,9 @@ def fetch_artifacts(target, build_id, artifact_path):
|
||||
def repo_for_sdk(filename):
|
||||
module = filename.split('-')[0]
|
||||
target_dir = ''
|
||||
if module == 'btservices': return Path('prebuilts/module_sdk/Bluetooth')
|
||||
if module == 'media': return Path('prebuilts/module_sdk/Media')
|
||||
if module == 'rkpd': return Path('prebuilts/module_sdk/RemoteKeyProvisioning')
|
||||
if module == 'tethering': return Path('prebuilts/module_sdk/Connectivity')
|
||||
for dir in os.listdir('prebuilts/module_sdk/'):
|
||||
if module.lower() in dir.lower():
|
||||
|
||||
Reference in New Issue
Block a user