Enable Automated Shadowed API Desugaring for the API usages of android.app.admin.FreezePeriod API
#desugar #automation
- Meanwhile, shadowed/mirrored core type converter classes are written by the desugar tool like runtime library classes, instead of from pre-stocked library dependency.
PiperOrigin-RevId: 304239033
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java b/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java
index d70d5b5..16b14f1 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/Desugar.java
@@ -31,6 +31,8 @@
import com.google.common.io.Resources;
import com.google.devtools.build.android.Converters.ExistingPathConverter;
import com.google.devtools.build.android.Converters.PathConverter;
+import com.google.devtools.build.android.desugar.corelibadapter.InvocationSiteTransformationRecord;
+import com.google.devtools.build.android.desugar.corelibadapter.InvocationSiteTransformationRecord.InvocationSiteTransformationRecordBuilder;
import com.google.devtools.build.android.desugar.corelibadapter.ShadowedApiAdaptersGenerator;
import com.google.devtools.build.android.desugar.corelibadapter.ShadowedApiInvocationSite;
import com.google.devtools.build.android.desugar.corelibadapter.ShadowedApiInvocationSite.ImmutableLabelRemover;
@@ -45,8 +47,6 @@
import com.google.devtools.build.android.desugar.io.ThrowingClassLoader;
import com.google.devtools.build.android.desugar.langmodel.ClassMemberUseCounter;
import com.google.devtools.build.android.desugar.langmodel.ClassName;
-import com.google.devtools.build.android.desugar.langmodel.InvocationSiteTransformationRecord;
-import com.google.devtools.build.android.desugar.langmodel.InvocationSiteTransformationRecord.InvocationSiteTransformationRecordBuilder;
import com.google.devtools.build.android.desugar.nest.NestAnalyzer;
import com.google.devtools.build.android.desugar.nest.NestDesugaring;
import com.google.devtools.build.android.desugar.nest.NestDigest;
@@ -554,14 +554,14 @@
copyRuntimeClasses(outputFileProvider, coreLibrarySupport);
- InvocationSiteTransformationRecord callSiteTransRecord = callSiteTransCollector.build();
- ImmutableList<FileContentProvider<ByteArrayInputStream>> coreLibAdapters =
- ShadowedApiAdaptersGenerator.generateAdapterClasses(callSiteTransRecord);
-
- for (FileContentProvider<ByteArrayInputStream> fileContent : coreLibAdapters) {
+ ShadowedApiAdaptersGenerator adaptersGenerator =
+ ShadowedApiAdaptersGenerator.create(callSiteTransCollector.build());
+ for (FileContentProvider<ByteArrayInputStream> fileContent :
+ adaptersGenerator.getApiAdapters()) {
outputFileProvider.write(
fileContent.getBinaryPathName(), ByteStreams.toByteArray(fileContent.get()));
}
+ copyTypeConverterClasses(outputFileProvider, adaptersGenerator.getTypeConverters());
byte[] depsInfo = depsCollector.toByteArray();
if (depsInfo != null) {
@@ -575,6 +575,18 @@
checkState(generatedLeftBehind.isEmpty(), "Didn't process %s", generatedLeftBehind.keySet());
}
+ private static void copyTypeConverterClasses(
+ OutputFileProvider outputFileProvider, ImmutableList<ClassName> converterClasses) {
+ for (ClassName className : converterClasses) {
+ String resourceName = className.classFilePathName();
+ try (InputStream stream = Resources.getResource(resourceName).openStream()) {
+ outputFileProvider.write(resourceName, ByteStreams.toByteArray(stream));
+ } catch (IOException e) {
+ throw new IOError(e);
+ }
+ }
+ }
+
/**
* Returns a dependency collector for use with a single input Jar. If {@link
* DesugarOptions#emitDependencyMetadata} is set, this method instantiates the collector
@@ -706,7 +718,7 @@
// The runtime library typically uses constructs we'd otherwise desugar, so it's easier
// to just skip it should it appear as a regular input (for idempotency).
if (inputFilename.endsWith(".class")
- && ClassName.fromClassFileName(inputFilename).isDesugarEligible(options.coreLibrary)) {
+ && ClassName.fromClassFileName(inputFilename).isDesugarEligible()) {
ClassReader reader = rewriter.reader(content);
UnprefixingClassWriter writer = rewriter.writer(ClassWriter.COMPUTE_MAXS);
ClassVisitor visitor =
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/langmodel/InvocationSiteTransformationRecord.java b/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/InvocationSiteTransformationRecord.java
similarity index 61%
rename from src/tools/android/java/com/google/devtools/build/android/desugar/langmodel/InvocationSiteTransformationRecord.java
rename to src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/InvocationSiteTransformationRecord.java
index b95ea0d..091d6f1 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/langmodel/InvocationSiteTransformationRecord.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/InvocationSiteTransformationRecord.java
@@ -1,12 +1,9 @@
/*
* Copyright 2020 The Bazel Authors. All rights reserved.
- *
* 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.
@@ -14,16 +11,19 @@
* limitations under the License.
*/
-package com.google.devtools.build.android.desugar.langmodel;
+package com.google.devtools.build.android.desugar.corelibadapter;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.android.desugar.langmodel.MethodInvocationSite;
/** A record that tracks the method invocation transformations. */
@AutoValue
public abstract class InvocationSiteTransformationRecord {
- public abstract ImmutableSet<MethodInvocationSite> record();
+ abstract ImmutableSet<MethodInvocationSite> adapterReplacements();
+
+ abstract ImmutableSet<MethodInvocationSite> inlineConversions();
public static InvocationSiteTransformationRecordBuilder builder() {
return new AutoValue_InvocationSiteTransformationRecord.Builder();
@@ -33,11 +33,19 @@
@AutoValue.Builder
public abstract static class InvocationSiteTransformationRecordBuilder {
- abstract ImmutableSet.Builder<MethodInvocationSite> recordBuilder();
+ abstract ImmutableSet.Builder<MethodInvocationSite> adapterReplacementsBuilder();
- public final InvocationSiteTransformationRecordBuilder addTransformation(
+ final InvocationSiteTransformationRecordBuilder addAdapterReplacement(
MethodInvocationSite originalMethodInvocationSite) {
- recordBuilder().add(originalMethodInvocationSite);
+ adapterReplacementsBuilder().add(originalMethodInvocationSite);
+ return this;
+ }
+
+ abstract ImmutableSet.Builder<MethodInvocationSite> inlineConversionsBuilder();
+
+ final InvocationSiteTransformationRecordBuilder addInlineConversion(
+ MethodInvocationSite originalMethodInvocationSite) {
+ inlineConversionsBuilder().add(originalMethodInvocationSite);
return this;
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/ShadowedApiAdaptersGenerator.java b/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/ShadowedApiAdaptersGenerator.java
index 732b732..66923f7 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/ShadowedApiAdaptersGenerator.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/ShadowedApiAdaptersGenerator.java
@@ -28,11 +28,11 @@
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.android.desugar.io.FileContentProvider;
import com.google.devtools.build.android.desugar.langmodel.ClassName;
-import com.google.devtools.build.android.desugar.langmodel.InvocationSiteTransformationRecord;
import com.google.devtools.build.android.desugar.langmodel.MethodDeclInfo;
import com.google.devtools.build.android.desugar.langmodel.MethodInvocationSite;
import com.google.devtools.build.android.desugar.langmodel.MethodKey;
import java.io.ByteArrayInputStream;
+import java.util.stream.Stream;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
@@ -41,8 +41,8 @@
/**
* Generates type adapter classes with methods that bridge the interactions between
- * desugared-mirrored types and their desugar-shadowed built-in types, and delivers the generated
- * classes to runtime library.
+ * desugared-mirrored types and their desugar-shadowed built-in types. Together with the necessary
+ * type converter classes, the class delivers the generated adapter classes to runtime library.
*/
public final class ShadowedApiAdaptersGenerator {
@@ -55,15 +55,6 @@
/** A record with evolving map values that track adapter classes to be generated. */
private final ImmutableMap<ClassName, ClassWriter> typeAdapters;
- /** The public API that provides the file content of generate adapter classes. */
- public static ImmutableList<FileContentProvider<ByteArrayInputStream>> generateAdapterClasses(
- InvocationSiteTransformationRecord callSiteTransformations) {
- return emitClassWriters(callSiteTransformations)
- .emitAdapterMethods()
- .closeClassWriters()
- .provideFileContents();
- }
-
private ShadowedApiAdaptersGenerator(
InvocationSiteTransformationRecord invocationAdapterSites,
ImmutableMap<ClassName, ClassWriter> typeAdapters) {
@@ -71,11 +62,17 @@
this.typeAdapters = typeAdapters;
}
+ /** The public factory method to construct {@link ShadowedApiAdaptersGenerator}. */
+ public static ShadowedApiAdaptersGenerator create(
+ InvocationSiteTransformationRecord callSiteTransformations) {
+ return emitClassWriters(callSiteTransformations).emitAdapterMethods().closeClassWriters();
+ }
+
private static ShadowedApiAdaptersGenerator emitClassWriters(
InvocationSiteTransformationRecord callSiteTransformations) {
return new ShadowedApiAdaptersGenerator(
callSiteTransformations,
- callSiteTransformations.record().stream()
+ callSiteTransformations.adapterReplacements().stream()
.map(ShadowedApiAdapterHelper::getAdapterInvocationSite)
.map(MethodInvocationSite::owner)
.distinct()
@@ -97,8 +94,36 @@
return cw;
}
+ /** Returns desugar-shadowed API adapters with desugar-mirrored types. */
+ public ImmutableList<FileContentProvider<ByteArrayInputStream>> getApiAdapters() {
+ return typeAdapters.entrySet().stream()
+ .map(
+ e ->
+ new FileContentProvider<>(
+ e.getKey().classFilePathName(),
+ () -> new ByteArrayInputStream(e.getValue().toByteArray())))
+ .collect(toImmutableList());
+ }
+
+ /**
+ * Returns type conversion classes that converts between a desugar-shadowed type and its
+ * deusgar-mirrored counterpart.
+ */
+ public ImmutableList<ClassName> getTypeConverters() {
+ return Stream.concat(
+ invocationAdapterSites.inlineConversions().stream(),
+ invocationAdapterSites.adapterReplacements().stream())
+ .flatMap(
+ site ->
+ Stream.concat(Stream.of(site.returnTypeName()), site.argumentTypeNames().stream()))
+ .filter(ClassName::isDesugarShadowedType)
+ .distinct()
+ .map(ClassName::typeConverterOwner)
+ .collect(toImmutableList());
+ }
+
private ShadowedApiAdaptersGenerator emitAdapterMethods() {
- for (MethodInvocationSite invocationSite : invocationAdapterSites.record()) {
+ for (MethodInvocationSite invocationSite : invocationAdapterSites.adapterReplacements()) {
MethodInvocationSite adapterSite =
ShadowedApiAdapterHelper.getAdapterInvocationSite(invocationSite);
ClassName adapterOwner = adapterSite.owner();
@@ -154,14 +179,4 @@
typeAdapters.values().forEach(ClassVisitor::visitEnd);
return this;
}
-
- private ImmutableList<FileContentProvider<ByteArrayInputStream>> provideFileContents() {
- return typeAdapters.entrySet().stream()
- .map(
- e ->
- new FileContentProvider<>(
- e.getKey().classFilePathName(),
- () -> new ByteArrayInputStream(e.getValue().toByteArray())))
- .collect(toImmutableList());
- }
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/ShadowedApiInvocationSite.java b/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/ShadowedApiInvocationSite.java
index 163cdcf..4c81fd3 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/ShadowedApiInvocationSite.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/corelibadapter/ShadowedApiInvocationSite.java
@@ -25,8 +25,8 @@
import static com.google.devtools.build.android.desugar.langmodel.ClassName.SHADOWED_TO_MIRRORED_TYPE_MAPPER;
import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.android.desugar.corelibadapter.InvocationSiteTransformationRecord.InvocationSiteTransformationRecordBuilder;
import com.google.devtools.build.android.desugar.langmodel.ClassName;
-import com.google.devtools.build.android.desugar.langmodel.InvocationSiteTransformationRecord.InvocationSiteTransformationRecordBuilder;
import com.google.devtools.build.android.desugar.langmodel.LangModelHelper;
import com.google.devtools.build.android.desugar.langmodel.MethodInvocationSite;
import com.google.devtools.build.android.desugar.langmodel.MethodKey;
@@ -134,6 +134,7 @@
SHADOWED_TO_MIRRORED_TYPE_MAPPER.map(verbatimInvocationSite.argumentTypeNames()),
verbatimInvocationSite.argumentTypeNames(),
INLINE_PARAM_TYPE_CONVERSION_TAG + verbatimInvocationSite.method().encode());
+ invocationSiteRecord.addInlineConversion(verbatimInvocationSite);
verbatimInvocationSite.accept(paramInlineInstructionsContainer);
MethodRemapper methodRemapper = new MethodRemapper(mv, IMMUTABLE_LABEL_ATTACHER);
@@ -145,7 +146,7 @@
checkState(!immutableLabelApplicator.isSwitchOn());
MethodInvocationSite adapterSite =
ShadowedApiAdapterHelper.getAdapterInvocationSite(verbatimInvocationSite);
- invocationSiteRecord.addTransformation(verbatimInvocationSite);
+ invocationSiteRecord.addAdapterReplacement(verbatimInvocationSite);
adapterSite.acceptTypeMapper(IMMUTABLE_LABEL_ATTACHER).accept(mv);
return;
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/langmodel/ClassName.java b/src/tools/android/java/com/google/devtools/build/android/desugar/langmodel/ClassName.java
index 01ec25e..a7a9179 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/langmodel/ClassName.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/langmodel/ClassName.java
@@ -83,7 +83,10 @@
.build();
private static final ImmutableBiMap<String, String> SHADOWED_MIRRORED_TYPE_PREFIX_MAPPINGS =
- ImmutableBiMap.<String, String>builder().put("javadesugar/", "jd$/").build();
+ ImmutableBiMap.<String, String>builder()
+ .put("java/", "j$/")
+ .put("javadesugar/", "jd$/")
+ .build();
public static final TypeMapper SHADOWED_TO_MIRRORED_TYPE_MAPPER =
new TypeMapper(ClassName::shadowedToMirrored);
public static final TypeMapper IMMUTABLE_LABEL_ATTACHER =
@@ -273,19 +276,14 @@
return prefixes.stream().anyMatch(this::hasPackagePrefix);
}
- public final boolean isDesugarEligible(boolean enableDesugarBuiltinJdk) {
- if (isDesugarShadowedType()) {
- return enableDesugarBuiltinJdk;
- }
- return !isInPackageEligibleForTypeAdapter()
- && !isInDesugarRuntimeLibrary()
- && !isDesugarMirroredType();
+ public final boolean isDesugarEligible() {
+ return !isInDesugarRuntimeLibrary();
}
public final boolean isInPackageEligibleForTypeAdapter() {
// TODO(b/152573900): Update to hasPackagePrefix("android/") once all package-wise incremental
// rollouts are complete.
- return hasAnyPackagePrefix("android/testing/");
+ return hasAnyPackagePrefix("android/testing/", "android/app/admin/FreezePeriod");
}
public final boolean isInDesugarRuntimeLibrary() {
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/TimeConversions.java b/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/TimeConversions.java
index 8292c2e..9040f26 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/TimeConversions.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/TimeConversions.java
@@ -27,40 +27,11 @@
return builder.setReferenceTime(toZonedDateTime(arg));
}
- /** The factory method for the {@link android.app.admin.FreezePeriod}. */
- @SuppressWarnings("MethodName") // synthetic method.
- public static android.app.admin.FreezePeriod create$FreezePeriod(
- j$.time.MonthDay jStart, j$.time.MonthDay jEnd) {
- java.time.MonthDay start = toMonthDay(jStart);
- java.time.MonthDay end = toMonthDay(jEnd);
- return new android.app.admin.FreezePeriod(start, end);
- }
-
- public static j$.time.MonthDay getStart(android.app.admin.FreezePeriod freezePeriod) {
- return fromMonthDay(freezePeriod.getStart());
- }
-
- public static j$.time.MonthDay getEnd(android.app.admin.FreezePeriod freezePeriod) {
- return fromMonthDay(freezePeriod.getEnd());
- }
-
public static j$.time.ZonedDateTime getReferenceTime(
android.view.textclassifier.TextClassification.Request request) {
return fromZonedDateTime(request.getReferenceTime());
}
- private static j$.time.MonthDay fromMonthDay(java.time.MonthDay monthDay) {
- return monthDay == null
- ? null
- : j$.time.MonthDay.of(monthDay.getMonthValue(), monthDay.getDayOfMonth());
- }
-
- private static java.time.MonthDay toMonthDay(j$.time.MonthDay monthDay) {
- return monthDay == null
- ? null
- : java.time.MonthDay.of(monthDay.getMonthValue(), monthDay.getDayOfMonth());
- }
-
private static j$.time.ZonedDateTime fromZonedDateTime(java.time.ZonedDateTime dateTime) {
if (dateTime == null) {
return null;
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/typeadapter/java/time/LocalDateConverter.java b/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/typeadapter/java/time/LocalDateConverter.java
new file mode 100644
index 0000000..cb44558
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/typeadapter/java/time/LocalDateConverter.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2020 The Bazel Authors. All rights reserved.
+ * 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 desugar.runtime.typeadapter.java.time;
+
+/** Converts types between the desugar-mirrored and desugar-shadowed {@link java.time.LocalDate}. */
+@SuppressWarnings("AndroidJdkLibsChecker")
+public abstract class LocalDateConverter {
+
+ private LocalDateConverter() {}
+
+ public static j$.time.LocalDate from(java.time.LocalDate localDate) {
+ return localDate == null
+ ? null
+ : j$.time.LocalDate.of(
+ localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
+ }
+
+ public static java.time.LocalDate to(j$.time.LocalDate localDate) {
+ return localDate == null
+ ? null
+ : java.time.LocalDate.of(
+ localDate.getYear(), localDate.getMonthValue(), localDate.getDayOfMonth());
+ }
+}
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/typeadapter/java/time/MonthDayConverter.java b/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/typeadapter/java/time/MonthDayConverter.java
new file mode 100644
index 0000000..917d49a
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/runtime/typeadapter/java/time/MonthDayConverter.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 The Bazel Authors. All rights reserved.
+ * 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 desugar.runtime.typeadapter.java.time;
+
+/** Converts types between the desugar-mirrored and desugar-shadowed {@link java.time.MonthDay}. */
+@SuppressWarnings("AndroidJdkLibsChecker")
+public abstract class MonthDayConverter {
+
+ private MonthDayConverter() {}
+
+ public static j$.time.MonthDay from(java.time.MonthDay monthDay) {
+ return monthDay == null
+ ? null
+ : j$.time.MonthDay.of(monthDay.getMonthValue(), monthDay.getDayOfMonth());
+ }
+
+ public static java.time.MonthDay to(j$.time.MonthDay monthDay) {
+ return monthDay == null
+ ? null
+ : java.time.MonthDay.of(monthDay.getMonthValue(), monthDay.getDayOfMonth());
+ }
+}