Remove API level signifying an android platform build
Any API level over the latest known and supported API level is treated
uniformly by the compiler. In particular the assume values rule created
by the compiler for Build.VERSION.SDK_INT is always the range excluding
the latest known API level and up to including MAX_INT.
Bug: b/232073181
Change-Id: I9059acf07d710d9db20c837239f529b8c760f67d
diff --git a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
index 44e051b..d96e654 100644
--- a/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCompilerCommand.java
@@ -842,7 +842,7 @@
reporter.error(builder.toString());
}
if (getMinApiLevel() > AndroidApiLevel.LATEST.getLevel()) {
- if (getMinApiLevel() != AndroidApiLevel.ANDROID_PLATFORM.getLevel()) {
+ if (getMinApiLevel() != AndroidApiLevel.ANDROID_PLATFORM_CONSTANT) {
reporter.warning(
"An API level of "
+ getMinApiLevel()
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java
index 1b732da..3821b7f 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java
@@ -21,16 +21,13 @@
public AndroidApiLevelCompute() {
knownApiLevelCache = new KnownApiLevel[AndroidApiLevel.API_DATABASE_LEVEL.getLevel() + 1];
for (AndroidApiLevel value : AndroidApiLevel.values()) {
- if (value != AndroidApiLevel.ANDROID_PLATFORM && value != AndroidApiLevel.MASTER) {
+ if (value != AndroidApiLevel.MASTER) {
knownApiLevelCache[value.getLevel()] = new KnownApiLevel(value);
}
}
}
public KnownApiLevel of(AndroidApiLevel apiLevel) {
- if (apiLevel == AndroidApiLevel.ANDROID_PLATFORM) {
- return ComputedApiLevel.platform();
- }
if (apiLevel == AndroidApiLevel.MASTER) {
return ComputedApiLevel.master();
}
@@ -76,9 +73,6 @@
}
public ComputedApiLevel computeInitialMinApiLevel(InternalOptions options) {
- if (options.getMinApiLevel() == AndroidApiLevel.ANDROID_PLATFORM) {
- return ComputedApiLevel.platform();
- }
if (options.getMinApiLevel() == AndroidApiLevel.MASTER) {
return ComputedApiLevel.master();
}
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java
index 2c6d00d..04f10d8 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.androidapi;
import static com.android.tools.r8.lightir.ByteUtils.isU2;
-import static com.android.tools.r8.utils.AndroidApiLevel.ANDROID_PLATFORM;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.graph.DexField;
@@ -20,6 +19,7 @@
import java.io.IOException;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
public class AndroidApiLevelHashingDatabaseImpl implements AndroidApiLevelDatabase {
@@ -125,7 +125,8 @@
return (byte) value;
}
- private final Map<DexReference, AndroidApiLevel> lookupCache = new ConcurrentHashMap<>();
+ private final Map<DexReference, Optional<AndroidApiLevel>> lookupCache =
+ new ConcurrentHashMap<>();
private final Map<DexString, Integer> constantPoolCache = new ConcurrentHashMap<>();
private final InternalOptions options;
private final DiagnosticsHandler diagnosticsHandler;
@@ -154,7 +155,8 @@
// Do not use computeIfAbsent since a return value of null implies the key should not be
// inserted.
lookupCache.put(
- predefinedApiReference.getReference(), predefinedApiReference.getApiLevel());
+ predefinedApiReference.getReference(),
+ Optional.of(predefinedApiReference.getApiLevel()));
});
assert predefinedApiTypeLookup.stream()
.allMatch(added -> added.getApiLevel().isEqualTo(lookupApiLevel(added.getReference())));
@@ -176,9 +178,7 @@
}
private AndroidApiLevel lookupApiLevel(DexReference reference) {
- // We use Android platform to track if an element is unknown since no occurrences of that api
- // level exists in the database.
- AndroidApiLevel result =
+ Optional<AndroidApiLevel> result =
lookupCache.computeIfAbsent(
reference,
ref -> {
@@ -187,7 +187,7 @@
getDataAccess(options, diagnosticsHandler);
}
if (dataAccess.isNoBacking()) {
- return ANDROID_PLATFORM;
+ return Optional.empty();
}
byte[] uniqueDescriptorForReference;
try {
@@ -201,15 +201,15 @@
uniqueDescriptorForReference = getNonExistingDescriptor();
}
if (uniqueDescriptorForReference == getNonExistingDescriptor()) {
- return ANDROID_PLATFORM;
+ return Optional.empty();
} else {
byte apiLevelForReference =
dataAccess.getApiLevelForReference(uniqueDescriptorForReference, ref);
return (apiLevelForReference <= 0)
- ? ANDROID_PLATFORM
- : AndroidApiLevel.getAndroidApiLevel(apiLevelForReference);
+ ? Optional.empty()
+ : Optional.of(AndroidApiLevel.getAndroidApiLevel(apiLevelForReference));
}
});
- return result == ANDROID_PLATFORM ? null : result;
+ return result.orElse(null);
}
}
diff --git a/src/main/java/com/android/tools/r8/androidapi/ComputedApiLevel.java b/src/main/java/com/android/tools/r8/androidapi/ComputedApiLevel.java
index 51394a9..24b7251 100644
--- a/src/main/java/com/android/tools/r8/androidapi/ComputedApiLevel.java
+++ b/src/main/java/com/android/tools/r8/androidapi/ComputedApiLevel.java
@@ -23,10 +23,6 @@
return UnknownApiLevel.INSTANCE;
}
- static KnownApiLevel platform() {
- return KnownApiLevel.PLATFORM_INSTANCE;
- }
-
static KnownApiLevel master() {
return KnownApiLevel.MASTER_INSTANCE;
}
@@ -165,9 +161,6 @@
class KnownApiLevel implements ComputedApiLevel {
- private static final KnownApiLevel PLATFORM_INSTANCE =
- new KnownApiLevel(AndroidApiLevel.ANDROID_PLATFORM);
-
private static final KnownApiLevel MASTER_INSTANCE = new KnownApiLevel(AndroidApiLevel.MASTER);
private final AndroidApiLevel apiLevel;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index bfcb585..a0d5ccb 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -347,7 +347,7 @@
}
private boolean typeIsPresentWithoutNeverIntroducedBackports(DexType type) {
- return typeIsPresentWithoutBackportsFrom(type, AndroidApiLevel.ANDROID_PLATFORM);
+ return typeIsPresentWithoutBackportsFrom(type, AndroidApiLevel.UNKNOWN);
}
private boolean typeIsPresentWithoutBackportsFrom(DexType type, AndroidApiLevel methodsMinAPI) {
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
index eba3341..b2d2536 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevel.java
@@ -44,8 +44,7 @@
Sv2(32),
T(33),
U(34),
- MASTER(35), // API level for master is tentative.
- ANDROID_PLATFORM(10000);
+ MASTER(35); // API level for master is tentative.
// When updating LATEST and a new version goes public, add a new api-versions.xml to third_party
// and update the version and generated jar in AndroidApiDatabaseBuilderGeneratorTest. Together
@@ -55,6 +54,11 @@
public static final AndroidApiLevel API_DATABASE_LEVEL = LATEST;
+ public static final AndroidApiLevel UNKNOWN = MASTER;
+
+ /** Constant used to signify some unknown min api when compiling platform. */
+ public static final int ANDROID_PLATFORM_CONSTANT = 10000;
+
private final int level;
AndroidApiLevel(int level) {
@@ -102,7 +106,7 @@
case V40:
return AndroidApiLevel.R;
case V41:
- return AndroidApiLevel.ANDROID_PLATFORM;
+ return AndroidApiLevel.MASTER;
default:
throw new Unreachable();
}
@@ -111,7 +115,7 @@
public static AndroidApiLevel getAndroidApiLevel(int apiLevel) {
assert apiLevel > 0;
assert U == LATEST; // This has to be updated when we add new api levels.
- assert ANDROID_PLATFORM.isGreaterThan(LATEST);
+ assert UNKNOWN.isGreaterThan(LATEST);
switch (apiLevel) {
case 1:
return B;
@@ -181,12 +185,8 @@
return T;
case 34:
return U;
- case 35:
- return MASTER;
- case 10000:
- return ANDROID_PLATFORM;
default:
- return LATEST;
+ return MASTER;
}
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/DexVersion.java b/src/main/java/com/android/tools/r8/utils/DexVersion.java
index cbfd8fc..f878e37 100644
--- a/src/main/java/com/android/tools/r8/utils/DexVersion.java
+++ b/src/main/java/com/android/tools/r8/utils/DexVersion.java
@@ -62,9 +62,7 @@
public static DexVersion getDexVersion(AndroidApiLevel androidApiLevel) {
switch (androidApiLevel) {
- // ANDROID_PLATFORM is an unknown higher api version we therefore choose the highest known
- // version.
- case ANDROID_PLATFORM:
+ // MASTER is an unknown higher api version we therefore choose the highest known version.
case MASTER:
case U:
case T:
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 17bf009..9e759dc 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -2636,7 +2636,7 @@
}
public boolean enableBackportedMethodRewriting() {
- return desugarState.isOn() && minApiLevel.isLessThan(AndroidApiLevel.ANDROID_PLATFORM);
+ return desugarState.isOn();
}
public boolean enableTryWithResourcesDesugaring() {
diff --git a/src/test/java/com/android/tools/r8/JvmTestBuilder.java b/src/test/java/com/android/tools/r8/JvmTestBuilder.java
index f6fcb08..f919181 100644
--- a/src/test/java/com/android/tools/r8/JvmTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/JvmTestBuilder.java
@@ -197,7 +197,7 @@
}
public JvmTestBuilder addAndroidBuildVersion() {
- return addAndroidBuildVersion(AndroidApiLevel.ANDROID_PLATFORM);
+ return addAndroidBuildVersion(AndroidApiLevel.MASTER);
}
public JvmTestBuilder addAndroidBuildVersion(AndroidApiLevel apiLevel) {
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 73236aa..ee9d68e 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -1144,7 +1144,6 @@
case J_MR1:
case J_MR2:
case K_WATCH:
- case ANDROID_PLATFORM:
return false;
default:
return true;
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java b/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
index 8eff1c5..16cd5d1 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ApiLevelBackportsTest.java
@@ -80,7 +80,7 @@
public void warningForFutureNonPlatformBuild() throws Exception {
testForD8()
.addProgramClassFileData(transformTestMathMultiplyExactLongInt())
- .setMinApi(AndroidApiLevel.LATEST.getLevel() + 1)
+ .setMinApi(AndroidApiLevel.UNKNOWN.getLevel())
.compile()
.assertOnlyWarnings()
.assertWarningMessageThatMatches(containsString("is not supported by this compiler"))
@@ -99,7 +99,9 @@
public void noWarningForPlatformBuild() throws Exception {
testForD8()
.addProgramClassFileData(transformTestMathMultiplyExactLongInt())
- .setMinApi(AndroidApiLevel.ANDROID_PLATFORM)
+ .setMinApi(AndroidApiLevel.ANDROID_PLATFORM_CONSTANT)
+ .compile()
+ .assertNoMessages()
.run(parameters.getRuntime(), TestMathMultiplyExactLongInt.class)
.applyIf(
parameters.getDexRuntimeVersion().isOlderThan(Version.V13_0_0),
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/BackportPlatformTest.java b/src/test/java/com/android/tools/r8/desugar/backports/BackportPlatformTest.java
index 5a2956c..2a811a6 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/BackportPlatformTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/BackportPlatformTest.java
@@ -107,7 +107,7 @@
assertEquals(AndroidApiLevel.J, parameters.getApiLevel());
testForD8(parameters.getBackend())
// Setting platform API will disable any error checking.
- .setMinApi(AndroidApiLevel.ANDROID_PLATFORM)
+ .setMinApi(AndroidApiLevel.ANDROID_PLATFORM_CONSTANT)
.apply(b -> b.getBuilder().setAndroidPlatformBuild(true))
.addOptionsModification(o -> o.disableBackportsWithErrorDiagnostics = true)
.addProgramClasses(CLASSES)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/legacy/L8TestWithLegacySpecification.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/legacy/L8TestWithLegacySpecification.java
index c0e4cf6..f150bbe 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/legacy/L8TestWithLegacySpecification.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/legacy/L8TestWithLegacySpecification.java
@@ -46,8 +46,7 @@
Arrays.stream(AndroidApiLevel.values())
.sorted()
.filter(apiLevel -> apiLevel.isGreaterThanOrEqualTo(AndroidApiLevel.L))
- .filter(apiLevel -> apiLevel.isLessThan(AndroidApiLevel.ANDROID_PLATFORM))
- .filter(apiLevel -> apiLevel != AndroidApiLevel.MASTER)
+ .filter(apiLevel -> apiLevel.isLessThan(AndroidApiLevel.MASTER))
.collect(Collectors.toList()),
CompilationMode.values(),
ImmutableList.of(
diff --git a/src/test/java/com/android/tools/r8/shaking/assumevalues/SynthesizedRulesFromApiLevelTest.java b/src/test/java/com/android/tools/r8/shaking/assumevalues/SynthesizedRulesFromApiLevelTest.java
index c61b850..76b2019 100644
--- a/src/test/java/com/android/tools/r8/shaking/assumevalues/SynthesizedRulesFromApiLevelTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/assumevalues/SynthesizedRulesFromApiLevelTest.java
@@ -5,10 +5,12 @@
package com.android.tools.r8.shaking.assumevalues;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.D8;
@@ -350,4 +352,34 @@
SynthesizedRule.PRESENT);
}
}
+
+ @Test
+ public void testUnknownApiLevelRule() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ List<ProguardConfigurationRule> rules =
+ testForR8(parameters.getBackend())
+ .addProgramClasses(TestClass.class)
+ .addKeepMainRule(TestClass.class)
+ .setMinApi(AndroidApiLevel.ANDROID_PLATFORM_CONSTANT)
+ .compile()
+ .getSyntheticProguardRules();
+ for (ProguardConfigurationRule rule : rules) {
+ String ruleText = rule.toString();
+ if (ruleText.contains("SDK_INT")) {
+ assertThat(
+ ruleText,
+ containsString(
+ "return " + AndroidApiLevel.UNKNOWN.getLevel() + ".." + Integer.MAX_VALUE));
+ return;
+ }
+ }
+ fail("Expected to find rule for SDK_INT value range");
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ System.out.println("Hello!");
+ }
+ }
}