Revert "[ApiModel] Outline calls to holders where definition is in library"
This reverts commit cc92ef376b6033ff631098046031923f40a4aa53.
Reason for revert: Breaking the bots
Change-Id: I6f61c1dd937de4ae3b0b4fb39b6b84058ddaf66e
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index 1536cd8..369e60c 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -191,9 +191,9 @@
* given type is *not* visited. The function indicates if traversal should continue or break. The
* result of the traversal is BREAK iff the function returned BREAK.
*/
- public <B> TraversalContinuation<B, ?> traverseSuperTypes(
+ public TraversalContinuation<?, ?> traverseSuperTypes(
final DexClass clazz,
- TriFunction<DexType, DexClass, Boolean, TraversalContinuation<B, ?>> fn) {
+ TriFunction<DexType, DexClass, Boolean, TraversalContinuation<?, ?>> fn) {
// We do an initial zero-allocation pass over the class super chain as it does not require a
// worklist/seen-set. Only if the traversal is not aborted and there actually are interfaces,
// do we continue traversal over the interface types. This is assuming that the second pass
@@ -206,7 +206,7 @@
if (currentClass.superType == null) {
break;
}
- TraversalContinuation<B, ?> stepResult =
+ TraversalContinuation<?, ?> stepResult =
fn.apply(currentClass.superType, currentClass, false);
if (stepResult.shouldBreak()) {
return stepResult;
@@ -226,7 +226,7 @@
while (currentClass != null) {
for (DexType iface : currentClass.interfaces.values) {
if (seen.add(iface)) {
- TraversalContinuation<B, ?> stepResult = fn.apply(iface, currentClass, true);
+ TraversalContinuation<?, ?> stepResult = fn.apply(iface, currentClass, true);
if (stepResult.shouldBreak()) {
return stepResult;
}
@@ -246,7 +246,7 @@
if (definition != null) {
for (DexType iface : definition.interfaces.values) {
if (seen.add(iface)) {
- TraversalContinuation<B, ?> stepResult = fn.apply(iface, definition, true);
+ TraversalContinuation<?, ?> stepResult = fn.apply(iface, definition, true);
if (stepResult.shouldBreak()) {
return stepResult;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
index 81beb5b..4c3fc63 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
@@ -40,8 +40,6 @@
import com.android.tools.r8.ir.synthetic.InstanceOfSourceCode;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.AndroidApiLevelUtils;
-import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.TraversalContinuation;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -121,33 +119,23 @@
return appView.computedMinApiLevel();
}
DexClass holder = appView.definitionFor(reference.getContextType());
- if (holder == null) {
+ if (holder == null || !holder.isLibraryClass()) {
return appView.computedMinApiLevel();
}
- Pair<DexClass, ComputedApiLevel> classAndApiLevel =
- AndroidApiLevelUtils.findAndComputeApiLevelForLibraryDefinition(
- appView, appView.appInfoForDesugaring(), holder, reference.asDexMember());
- ComputedApiLevel referenceApiLevel = classAndApiLevel.getSecond();
+ ComputedApiLevel referenceApiLevel =
+ apiLevelCompute.computeApiLevelForLibraryReference(reference, ComputedApiLevel.unknown());
if (appView.computedMinApiLevel().isGreaterThanOrEqualTo(referenceApiLevel)
|| isApiLevelLessThanOrEqualTo9(referenceApiLevel)
|| referenceApiLevel.isUnknownApiLevel()) {
return appView.computedMinApiLevel();
}
- assert referenceApiLevel.isKnownApiLevel();
- DexClass firstLibraryClass = classAndApiLevel.getFirst();
- if (firstLibraryClass == null || !firstLibraryClass.isLibraryClass()) {
- assert false : "When computed a known api level we should always have a library class";
- return appView.computedMinApiLevel();
- }
// Check for protected or package private access flags before outlining.
- if (firstLibraryClass.isInterface()
- || instruction.isCheckCast()
- || instruction.isInstanceOf()) {
+ if (holder.isInterface() || instruction.isCheckCast() || instruction.isInstanceOf()) {
return referenceApiLevel;
} else {
DexEncodedMember<?, ?> definition =
simpleLookupInClassHierarchy(
- firstLibraryClass.asLibraryClass(),
+ holder.asLibraryClass(),
reference.isDexMethod()
? x -> x.lookupMethod(reference.asDexMethod())
: x -> x.lookupField(reference.asDexField()));
diff --git a/src/main/java/com/android/tools/r8/shaking/ComputeApiLevelUseRegistry.java b/src/main/java/com/android/tools/r8/shaking/ComputeApiLevelUseRegistry.java
index d779378..662f9f4 100644
--- a/src/main/java/com/android/tools/r8/shaking/ComputeApiLevelUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/shaking/ComputeApiLevelUseRegistry.java
@@ -7,9 +7,7 @@
import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.dex.code.CfOrDexInstruction;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
@@ -17,13 +15,11 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
-import com.android.tools.r8.utils.AndroidApiLevelUtils;
import java.util.ListIterator;
public class ComputeApiLevelUseRegistry extends UseRegistry<ProgramMethod> {
protected final AppView<?> appView;
- private final AppInfoWithClassHierarchy appInfoWithClassHierarchy;
private final AndroidApiLevelCompute apiLevelCompute;
private final boolean isEnabled;
private ComputedApiLevel maxApiReferenceLevel;
@@ -32,7 +28,6 @@
AppView<?> appView, ProgramMethod context, AndroidApiLevelCompute apiLevelCompute) {
super(appView, context);
this.appView = appView;
- this.appInfoWithClassHierarchy = appView.appInfoForDesugaring();
this.apiLevelCompute = apiLevelCompute;
isEnabled = apiLevelCompute.isEnabled();
maxApiReferenceLevel = appView.computedMinApiLevel();
@@ -153,28 +148,10 @@
private void setMaxApiReferenceLevel(DexReference reference) {
if (isEnabled) {
- if (reference.isDexType()) {
- maxApiReferenceLevel =
- maxApiReferenceLevel.max(
- apiLevelCompute.computeApiLevelForLibraryReference(
- reference, apiLevelCompute.getPlatformApiLevelOrUnknown(appView)));
- } else if (!reference.getContextType().isClassType()) {
- maxApiReferenceLevel = maxApiReferenceLevel.max(appView.computedMinApiLevel());
- } else {
- DexClass holder = appView.definitionFor(reference.getContextType());
- ComputedApiLevel referenceApiLevel = ComputedApiLevel.unknown();
- if (holder != null) {
- referenceApiLevel =
- AndroidApiLevelUtils.findAndComputeApiLevelForLibraryDefinition(
- appView, appInfoWithClassHierarchy, holder, reference.asDexMember())
- .getSecond();
- }
- maxApiReferenceLevel =
- maxApiReferenceLevel.max(
- referenceApiLevel.isUnknownApiLevel()
- ? apiLevelCompute.getPlatformApiLevelOrUnknown(appView)
- : referenceApiLevel);
- }
+ maxApiReferenceLevel =
+ maxApiReferenceLevel.max(
+ apiLevelCompute.computeApiLevelForLibraryReference(
+ reference, apiLevelCompute.getPlatformApiLevelOrUnknown(appView)));
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
index ec58eb5..7369593 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMember;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
@@ -23,9 +22,6 @@
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.optimize.inliner.NopWhyAreYouNotInliningReporter;
import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
-import com.google.common.collect.Sets;
-import java.util.Collections;
-import java.util.Set;
public class AndroidApiLevelUtils {
@@ -195,110 +191,4 @@
return oldBaseLibraryClass != null
&& isApiSafeForReference(newBaseLibraryClass, oldBaseLibraryClass, appView);
}
-
- public static Pair<DexClass, ComputedApiLevel> findAndComputeApiLevelForLibraryDefinition(
- AppView<?> appView,
- AppInfoWithClassHierarchy appInfo,
- DexClass holder,
- DexMember<?, ?> reference) {
- AndroidApiLevelCompute apiLevelCompute = appView.apiLevelCompute();
- if (holder.isLibraryClass()) {
- return Pair.create(
- holder,
- apiLevelCompute.computeApiLevelForLibraryReference(
- reference, ComputedApiLevel.unknown()));
- }
- // The API database do not allow for resolving into it (since that is not stable), and it is
- // therefore designed in a way where all members of classes can be queried on any sub-type with
- // the api level for where it is reachable. It is therefore sufficient for us, to figure out if
- // an instruction is a library call, to either find a program definition or to find the library
- // frontier.
- // Scan through the type hierarchy to find the first library class or program definition.
- DexClass firstClassWithReferenceOrLibraryClass =
- firstLibraryClassOrProgramClassWithDefinition(appInfo, holder, reference);
- if (firstClassWithReferenceOrLibraryClass == null) {
- return Pair.create(null, ComputedApiLevel.unknown());
- }
- if (!firstClassWithReferenceOrLibraryClass.isLibraryClass()) {
- return Pair.create(firstClassWithReferenceOrLibraryClass, appView.computedMinApiLevel());
- }
- ComputedApiLevel apiLevel =
- apiLevelCompute.computeApiLevelForLibraryReference(
- reference.withHolder(
- firstClassWithReferenceOrLibraryClass.getType(), appView.dexItemFactory()),
- ComputedApiLevel.unknown());
- if (apiLevel.isKnownApiLevel()) {
- return Pair.create(firstClassWithReferenceOrLibraryClass, apiLevel);
- }
- // We were unable to find a definition in the class hierarchy, check all interfaces for a
- // definition or the library interfaces for the first interface definition.
- Set<DexClass> firstLibraryInterfaces =
- findAllFirstLibraryInterfacesOrProgramClassWithDefinition(appInfo, holder, reference);
- if (firstLibraryInterfaces.size() == 1) {
- DexClass firstClass = firstLibraryInterfaces.iterator().next();
- if (firstClass.isProgramClass()) {
- return Pair.create(firstClass, appView.computedMinApiLevel());
- }
- }
- DexClass foundClass = null;
- ComputedApiLevel minApiLevel = ComputedApiLevel.unknown();
- for (DexClass libraryInterface : firstLibraryInterfaces) {
- assert libraryInterface.isLibraryClass();
- ComputedApiLevel libraryIfaceApiLevel =
- apiLevelCompute.computeApiLevelForLibraryReference(
- reference.withHolder(
- firstClassWithReferenceOrLibraryClass.getType(), appView.dexItemFactory()),
- ComputedApiLevel.unknown());
- if (minApiLevel.isGreaterThan(libraryIfaceApiLevel)) {
- minApiLevel = libraryIfaceApiLevel;
- foundClass = libraryInterface;
- }
- }
- return Pair.create(foundClass, minApiLevel);
- }
-
- private static DexClass firstLibraryClassOrProgramClassWithDefinition(
- AppInfoWithClassHierarchy appInfo, DexClass originalClass, DexMember<?, ?> reference) {
- if (originalClass.isLibraryClass()) {
- return originalClass;
- }
- WorkList<DexClass> workList = WorkList.newIdentityWorkList(originalClass);
- while (workList.hasNext()) {
- DexClass clazz = workList.next();
- if (clazz.isLibraryClass()) {
- return clazz;
- } else if (clazz.lookupMember(reference) != null) {
- return clazz;
- } else if (clazz.getSuperType() != null) {
- appInfo
- .contextIndependentDefinitionForWithResolutionResult(clazz.getSuperType())
- .forEachClassResolutionResult(workList::addIfNotSeen);
- }
- }
- return null;
- }
-
- private static Set<DexClass> findAllFirstLibraryInterfacesOrProgramClassWithDefinition(
- AppInfoWithClassHierarchy appInfo, DexClass originalClass, DexMember<?, ?> reference) {
- Set<DexClass> interfaces = Sets.newLinkedHashSet();
- WorkList<DexClass> workList = WorkList.newIdentityWorkList(originalClass);
- while (workList.hasNext()) {
- DexClass clazz = workList.next();
- if (clazz.isLibraryClass()) {
- if (clazz.isInterface()) {
- interfaces.add(clazz);
- }
- } else if (clazz.lookupMember(reference) != null) {
- return Collections.singleton(clazz);
- } else {
- clazz.forEachImmediateSupertype(
- superType -> {
- appInfo
- .contextIndependentDefinitionForWithResolutionResult(superType)
- .forEachClassResolutionResult(workList::addIfNotSeen);
- });
- }
- }
- return interfaces;
- }
}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithDifferentApiLevelTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithDifferentApiLevelTest.java
index 3c2923d..f859e30 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithDifferentApiLevelTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithDifferentApiLevelTest.java
@@ -20,7 +20,6 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.apimodel.ApiModelingTestHelper.ApiModelingMethodVerificationHelper;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.testing.AndroidBuildVersion;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -104,7 +103,7 @@
.apply(this::setupTestBuilder)
.compile()
.apply(this::setupRunEnvironment)
- .inspect(inspector -> inspect(inspector, false))
+ .inspect(this::inspect)
.run(parameters.getRuntime(), Main.class)
.apply(result -> checkOutput(result, false));
}
@@ -116,7 +115,7 @@
.apply(this::setupTestBuilder)
.compile()
.apply(this::setupRunEnvironment)
- .inspect(inspector -> inspect(inspector, false))
+ .inspect(this::inspect)
.run(parameters.getRuntime(), Main.class)
.apply(result -> checkOutput(result, false));
}
@@ -128,7 +127,7 @@
.addKeepMainRule(Main.class)
.addKeepClassAndMembersRules(ProgramJoiner.class)
.compile()
- .inspect(inspector -> inspect(inspector, true))
+ .inspect(this::inspect)
.apply(this::setupRunEnvironment)
.run(parameters.getRuntime(), Main.class)
.apply(result -> checkOutput(result, true));
@@ -156,25 +155,17 @@
result -> result.assertStderrMatches(not(containsString("This dex file is invalid"))));
}
- private void inspect(CodeInspector inspector, boolean isR8) throws Exception {
- ApiModelingMethodVerificationHelper verifyHelper =
- verifyThat(
+ private void inspect(CodeInspector inspector) throws Exception {
+ // TODO(b/254510678): We should outline the call to ProgramJoiner.foo.
+ verifyThat(
inspector,
parameters,
Reference.method(
- // TODO(b/254510678): Due to member rebinding, we rebind ProgramJoiner.foo() to
- // LibraryClass.foo().
- Reference.classFromClass(isR8 ? LibraryClass.class : ProgramJoiner.class),
+ Reference.classFromClass(ProgramJoiner.class),
"foo",
Collections.emptyList(),
- null));
- if (isR8 && parameters.isCfRuntime()) {
- verifyHelper.isOutlinedFromUntil(
- Main.class.getDeclaredMethod("main", String[].class), classMethodApiLevel);
- } else {
- verifyHelper.isOutlinedFromUntilAlsoForCf(
- Main.class.getDeclaredMethod("main", String[].class), classMethodApiLevel);
- }
+ null))
+ .isNotOutlinedFrom(Main.class.getDeclaredMethod("main", String[].class));
}
// Only present from api level 23.
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithSameApiLevelTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithSameApiLevelTest.java
index f6a0a49..a0cc571 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithSameApiLevelTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithSameApiLevelTest.java
@@ -20,7 +20,6 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.apimodel.ApiModelingTestHelper.ApiModelingMethodVerificationHelper;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.testing.AndroidBuildVersion;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -94,7 +93,7 @@
.apply(this::setupRunEnvironment)
.run(parameters.getRuntime(), Main.class)
.apply(result -> checkOutput(result, false))
- .inspect(inspector -> inspect(inspector, false));
+ .inspect(this::inspect);
}
@Test
@@ -106,7 +105,7 @@
.apply(this::setupRunEnvironment)
.run(parameters.getRuntime(), Main.class)
.apply(result -> checkOutput(result, false))
- .inspect(inspector -> inspect(inspector, false));
+ .inspect(this::inspect);
}
@Test
@@ -116,7 +115,7 @@
.addKeepMainRule(Main.class)
.addKeepClassAndMembersRules(ProgramJoiner.class)
.compile()
- .inspect(inspector -> inspect(inspector, true))
+ .inspect(this::inspect)
.apply(this::setupRunEnvironment)
.run(parameters.getRuntime(), Main.class)
.apply(result -> checkOutput(result, true));
@@ -138,25 +137,17 @@
result -> result.assertStderrMatches(not(containsString("This dex file is invalid"))));
}
- private void inspect(CodeInspector inspector, boolean isR8) throws Exception {
- ApiModelingMethodVerificationHelper verifyHelper =
- verifyThat(
+ private void inspect(CodeInspector inspector) throws Exception {
+ // TODO(b/254510678): We should outline the call to ProgramClass.foo.
+ verifyThat(
inspector,
parameters,
Reference.method(
- // TODO(b/254510678): Due to member rebinding, we rebind ProgramJoiner.foo() to
- // LibraryClass.foo().
- Reference.classFromClass(isR8 ? LibraryClass.class : ProgramJoiner.class),
+ Reference.classFromClass(ProgramJoiner.class),
"foo",
Collections.emptyList(),
- null));
- if (isR8 && parameters.isCfRuntime()) {
- verifyHelper.isOutlinedFromUntil(
- Main.class.getDeclaredMethod("main", String[].class), mockApiLevel);
- } else {
- verifyHelper.isOutlinedFromUntilAlsoForCf(
- Main.class.getDeclaredMethod("main", String[].class), mockApiLevel);
- }
+ null))
+ .isNotOutlinedFrom(Main.class.getDeclaredMethod("main", String[].class));
}
// Only present from api level 23.
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelOutlineSubTypeStaticReferenceTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelOutlineSubTypeStaticReferenceTest.java
index 19971c3..3e56179 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelOutlineSubTypeStaticReferenceTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelOutlineSubTypeStaticReferenceTest.java
@@ -7,6 +7,9 @@
import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForClass;
import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
import static com.android.tools.r8.apimodel.ApiModelingTestHelper.verifyThat;
+import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethod;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationMode;
@@ -20,8 +23,8 @@
import com.android.tools.r8.testing.AndroidBuildVersion;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.lang.reflect.Method;
-import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -130,14 +133,13 @@
Method otherMethod = Sub.class.getMethod("otherMethod");
Method libraryMethod = LibraryClass.class.getMethod("foo");
// TODO(b/254510678): R8 should not member-rebind to a potential non-existing method.
- verifyThat(
- inspector,
- parameters,
- isR8
- ? Reference.methodFromMethod(libraryMethod)
- : Reference.method(
- Reference.classFromClass(Sub.class), "foo", Collections.emptyList(), null))
- .isOutlinedFromUntil(Sub.class.getDeclaredMethod("otherMethod"), libraryApiLevel);
+ if (isR8) {
+ MethodSubject method = inspector.method(otherMethod);
+ assertThat(method, isPresent());
+ assertThat(method, invokesMethod(Reference.methodFromMethod(libraryMethod)));
+ }
+ // TODO(b/254510678): We should outline this up until library api level.
+ verifyThat(inspector, parameters, libraryMethod).isNotOutlinedFrom(otherMethod);
}
private void checkResultOnBootClassPath(SingleTestRunResult<?> runResult) {
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
index 1e45b00..e437943 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
@@ -447,14 +447,6 @@
}
}
- void isOutlinedFromUntilAlsoForCf(Executable method, AndroidApiLevel apiLevel) {
- if (parameters.getApiLevel().isLessThan(apiLevel)) {
- isOutlinedFrom(method);
- } else {
- isNotOutlinedFrom(method);
- }
- }
-
void isOutlinedFrom(Executable method) {
// Check that the call is in a synthetic class.
List<FoundMethodSubject> outlinedMethod =