blob: fec4b65d517ac5315d13f84f6f24bd308b9a042b [file] [log] [blame]
// Copyright (c) 2021, 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.androidapi;
import com.android.tools.r8.androidapi.ComputedApiLevel.KnownApiLevel;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMember;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions;
public abstract class AndroidApiLevelCompute {
private final KnownApiLevel[] knownApiLevelCache;
public AndroidApiLevelCompute() {
knownApiLevelCache = new KnownApiLevel[AndroidApiLevel.LATEST.getLevel() + 1];
for (AndroidApiLevel value : AndroidApiLevel.values()) {
if (value != AndroidApiLevel.ANDROID_PLATFORM) {
knownApiLevelCache[value.getLevel()] = new KnownApiLevel(value);
}
}
}
public KnownApiLevel of(AndroidApiLevel apiLevel) {
if (apiLevel == AndroidApiLevel.ANDROID_PLATFORM) {
return ComputedApiLevel.platform();
}
return knownApiLevelCache[apiLevel.getLevel()];
}
public abstract ComputedApiLevel computeApiLevelForLibraryReference(
DexReference reference, ComputedApiLevel unknownValue);
public abstract ComputedApiLevel computeApiLevelForDefinition(
Iterable<DexType> types, ComputedApiLevel unknownValue);
public ComputedApiLevel computeApiLevelForDefinition(
DexMember<?, ?> reference, DexItemFactory factory, ComputedApiLevel unknownValue) {
return computeApiLevelForDefinition(reference.getReferencedBaseTypes(factory), unknownValue);
}
public static AndroidApiLevelCompute create(AppView<?> appView) {
return appView.options().apiModelingOptions().enableApiCallerIdentification
? new DefaultAndroidApiLevelCompute(appView)
: noAndroidApiLevelCompute();
}
public static AndroidApiLevelCompute noAndroidApiLevelCompute() {
return new NoAndroidApiLevelCompute();
}
public ComputedApiLevel computeInitialMinApiLevel(InternalOptions options) {
return options.getMinApiLevel() == AndroidApiLevel.ANDROID_PLATFORM
? ComputedApiLevel.platform()
: new KnownApiLevel(options.getMinApiLevel());
}
public ComputedApiLevel getPlatformApiLevelOrUnknown(AppView<?> appView) {
if (appView.options().getMinApiLevel() == AndroidApiLevel.ANDROID_PLATFORM) {
return ComputedApiLevel.platform();
}
return ComputedApiLevel.unknown();
}
public static class NoAndroidApiLevelCompute extends AndroidApiLevelCompute {
@Override
public ComputedApiLevel computeApiLevelForDefinition(
Iterable<DexType> types, ComputedApiLevel unknownValue) {
return unknownValue;
}
@Override
public ComputedApiLevel computeApiLevelForLibraryReference(
DexReference reference, ComputedApiLevel unknownValue) {
return unknownValue;
}
@Override
public ComputedApiLevel computeInitialMinApiLevel(InternalOptions options) {
return ComputedApiLevel.unknown();
}
}
public static class DefaultAndroidApiLevelCompute extends AndroidApiLevelCompute {
private final AndroidApiReferenceLevelCache cache;
private final ComputedApiLevel minApiLevel;
public DefaultAndroidApiLevelCompute(AppView<?> appView) {
this.cache = AndroidApiReferenceLevelCache.create(appView, this);
this.minApiLevel = of(appView.options().getMinApiLevel());
}
@Override
public ComputedApiLevel computeApiLevelForDefinition(
Iterable<DexType> types, ComputedApiLevel unknownValue) {
ComputedApiLevel computedLevel = minApiLevel;
for (DexType type : types) {
computedLevel = cache.lookupMax(type, computedLevel, unknownValue);
}
return computedLevel;
}
@Override
public ComputedApiLevel computeApiLevelForLibraryReference(
DexReference reference, ComputedApiLevel unknownValue) {
return cache.lookup(reference, unknownValue);
}
}
}