blob: 84ce0fc79661541bb18d877c1c8fcce85b15766a [file]
// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.metadata.impl;
import com.android.tools.r8.dex.VirtualFile;
import com.android.tools.r8.keepanno.annotations.AnnotationPattern;
import com.android.tools.r8.keepanno.annotations.FieldAccessFlags;
import com.android.tools.r8.keepanno.annotations.KeepConstraint;
import com.android.tools.r8.keepanno.annotations.KeepItemKind;
import com.android.tools.r8.keepanno.annotations.UsedByReflection;
import com.android.tools.r8.metadata.R8BaselineProfileRewritingMetadata;
import com.android.tools.r8.metadata.R8BuildMetadata;
import com.android.tools.r8.metadata.R8DexFileMetadata;
import com.android.tools.r8.metadata.R8FeatureSplitsMetadata;
import com.android.tools.r8.metadata.R8OptionsMetadata;
import com.android.tools.r8.metadata.R8PartialCompilationMetadata;
import com.android.tools.r8.metadata.R8ResourceOptimizationMetadata;
import com.android.tools.r8.metadata.R8StartupOptimizationMetadata;
import com.android.tools.r8.metadata.R8StatsMetadata;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.SemanticVersion;
import com.google.gson.Gson;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
import java.util.function.Consumer;
@UsedByReflection(
description = "Keep and preserve @SerializedName for correct (de)serialization",
constraints = {KeepConstraint.LOOKUP},
constrainAnnotations = @AnnotationPattern(constant = SerializedName.class),
kind = KeepItemKind.CLASS_AND_FIELDS,
fieldAccess = {FieldAccessFlags.PRIVATE},
fieldAnnotatedByClassConstant = SerializedName.class)
public class R8BuildMetadataImpl implements R8BuildMetadata {
@Expose
@SerializedName("options")
private final R8OptionsMetadata optionsMetadata;
@Expose
@SerializedName("baselineProfileRewriting")
private final R8BaselineProfileRewritingMetadata baselineProfileRewritingMetadata;
@Expose
@SerializedName("dexFiles")
private final List<R8DexFileMetadata> dexFilesMetadata;
@Expose
@SerializedName("stats")
private final R8StatsMetadata statsMetadata;
@Expose
@SerializedName("featureSplits")
private final R8FeatureSplitsMetadata featureSplitsMetadata;
@Expose
@SerializedName("partialCompilation")
private final R8PartialCompilationMetadata partialCompilationMetadata;
@Expose
@SerializedName("resourceOptimization")
private final R8ResourceOptimizationMetadata resourceOptimizationMetadata;
@Expose
@SerializedName("startupOptimization")
private final R8StartupOptimizationMetadata startupOptimizationMetadata;
@Expose
@SerializedName("version")
private final String version;
public R8BuildMetadataImpl(
R8OptionsMetadata options,
R8BaselineProfileRewritingMetadata baselineProfileRewritingOptions,
List<R8DexFileMetadata> dexFilesMetadata,
R8StatsMetadata statsMetadata,
R8FeatureSplitsMetadata featureSplitsMetadata,
R8PartialCompilationMetadata partialCompilationMetadata,
R8ResourceOptimizationMetadata resourceOptimizationMetadata,
R8StartupOptimizationMetadata startupOptimizationMetadata,
String version) {
this.optionsMetadata = options;
this.baselineProfileRewritingMetadata = baselineProfileRewritingOptions;
this.dexFilesMetadata = dexFilesMetadata;
this.statsMetadata = canHaveOverflowInStatsMetadata(version) ? null : statsMetadata;
this.featureSplitsMetadata = featureSplitsMetadata;
this.partialCompilationMetadata = partialCompilationMetadata;
this.resourceOptimizationMetadata = resourceOptimizationMetadata;
this.startupOptimizationMetadata = startupOptimizationMetadata;
this.version = version;
}
public static boolean canHaveOverflowInStatsMetadata(String version) {
try {
SemanticVersion semanticVersion = SemanticVersion.parse(version);
switch (semanticVersion.getMajor()) {
case 8:
switch (semanticVersion.getMinor()) {
case 10:
// Fixed in 8.10.33.
return semanticVersion.getPatch() < 33;
case 11:
// Fixed in 8.11.23.
return semanticVersion.getPatch() < 23;
case 12:
// Fixed in 8.12.19.
return semanticVersion.getPatch() < 19;
case 13:
// Fixed in 8.13.4.
return semanticVersion.getPatch() < 4;
default:
// R8 build metadata was only available in R8 8.10, so this should always be false.
return semanticVersion.getMinor() < 10;
}
case 9:
// Fixed in 9.0.1-dev.
return semanticVersion.getMinor() == 0 && semanticVersion.getPatch() == 0;
default:
// R8 build metadata was only available in R8 8, so this should always be false.
return semanticVersion.getMajor() < 8;
}
} catch (Exception e) {
// Conservatively return true, for example, if the build metadata is from a main build.
return true;
}
}
public static Builder builder() {
return new Builder();
}
@Override
public R8OptionsMetadata getOptionsMetadata() {
return optionsMetadata;
}
@Override
public R8BaselineProfileRewritingMetadata getBaselineProfileRewritingMetadata() {
return baselineProfileRewritingMetadata;
}
@Override
public List<R8DexFileMetadata> getDexFilesMetadata() {
return dexFilesMetadata;
}
@Override
public R8FeatureSplitsMetadata getFeatureSplitsMetadata() {
return featureSplitsMetadata;
}
@Override
public R8PartialCompilationMetadata getPartialCompilationMetadata() {
return partialCompilationMetadata;
}
@Override
public R8ResourceOptimizationMetadata getResourceOptimizationMetadata() {
return resourceOptimizationMetadata;
}
@Override
public R8StartupOptimizationMetadata getStartupOptizationOptions() {
return startupOptimizationMetadata;
}
@Override
public R8StatsMetadata getStatsMetadata() {
return statsMetadata;
}
@Override
public String getVersion() {
return version;
}
@Override
public String toJson() {
return new Gson().toJson(this);
}
public static class Builder {
private R8OptionsMetadata options;
private R8BaselineProfileRewritingMetadata baselineProfileRewritingOptions;
private List<R8DexFileMetadata> dexFilesMetadata;
private R8StatsMetadata statsMetadata;
private R8FeatureSplitsMetadata featureSplitsMetadata;
private R8PartialCompilationMetadata partialCompilationMetadata;
private R8ResourceOptimizationMetadata resourceOptimizationOptions;
private R8StartupOptimizationMetadata startupOptimizationOptions;
private String version;
public Builder applyIf(boolean condition, Consumer<Builder> thenConsumer) {
if (condition) {
thenConsumer.accept(this);
}
return this;
}
public Builder setOptions(R8OptionsMetadata options) {
this.options = options;
return this;
}
public Builder setBaselineProfileRewritingOptions(
R8BaselineProfileRewritingMetadata baselineProfileRewritingOptions) {
this.baselineProfileRewritingOptions = baselineProfileRewritingOptions;
return this;
}
public Builder setDexFilesMetadata(List<VirtualFile> virtualFiles) {
this.dexFilesMetadata = ListUtils.map(virtualFiles, R8DexFileMetadataImpl::create);
return this;
}
public Builder setStatsMetadata(R8StatsMetadata statsMetadata) {
this.statsMetadata = statsMetadata;
return this;
}
public Builder setFeatureSplitsMetadata(R8FeatureSplitsMetadata featureSplitsMetadata) {
this.featureSplitsMetadata = featureSplitsMetadata;
return this;
}
public Builder setPartialCompilationMetadata(
R8PartialCompilationMetadata partialCompilationMetadata) {
this.partialCompilationMetadata = partialCompilationMetadata;
return this;
}
public Builder setResourceOptimizationOptions(
R8ResourceOptimizationMetadata resourceOptimizationOptions) {
this.resourceOptimizationOptions = resourceOptimizationOptions;
return this;
}
public Builder setStartupOptimizationOptions(
R8StartupOptimizationMetadata startupOptimizationOptions) {
this.startupOptimizationOptions = startupOptimizationOptions;
return this;
}
public Builder setVersion(String version) {
this.version = version;
return this;
}
public R8BuildMetadataImpl build() {
return new R8BuildMetadataImpl(
options,
baselineProfileRewritingOptions,
dexFilesMetadata,
statsMetadata,
featureSplitsMetadata,
partialCompilationMetadata,
resourceOptimizationOptions,
startupOptimizationOptions,
version);
}
}
}