Encapsulate fields in api modeling options

Change-Id: Idba70521ad7f554875358a9f5c72cfe7cd5136dc
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 96ceebf..2a2da45 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -841,8 +841,11 @@
     if (internal.isGeneratingClassFiles()
         || (System.getProperty("com.android.tools.r8.enableApiOutliningAndStubbing") == null
             && !enableMissingLibraryApiModeling)) {
-      internal.apiModelingOptions().disableApiCallerIdentification();
-      internal.apiModelingOptions().disableOutliningAndStubbing();
+      internal
+          .apiModelingOptions()
+          .disableApiCallerIdentification()
+          .disableOutlining()
+          .disableStubbingOfClasses();
     }
 
     if (enableRewritingOfArtProfilesIsNopCheck) {
diff --git a/src/main/java/com/android/tools/r8/GlobalSyntheticsGeneratorCommand.java b/src/main/java/com/android/tools/r8/GlobalSyntheticsGeneratorCommand.java
index 9ffc2e8..80a7691 100644
--- a/src/main/java/com/android/tools/r8/GlobalSyntheticsGeneratorCommand.java
+++ b/src/main/java/com/android/tools/r8/GlobalSyntheticsGeneratorCommand.java
@@ -147,8 +147,11 @@
         classfileDesugaringOnly ? new ThrowingCfConsumer() : new ThrowingDexConsumer();
     internal.setGlobalSyntheticsConsumer(globalsConsumer);
     if (classfileDesugaringOnly) {
-      internal.apiModelingOptions().disableApiCallerIdentification();
-      internal.apiModelingOptions().disableOutliningAndStubbing();
+      internal
+          .apiModelingOptions()
+          .disableApiCallerIdentification()
+          .disableOutlining()
+          .disableStubbingOfClasses();
     }
 
     // Assert and fixup defaults.
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 912ef55..7a47cdd 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -231,8 +231,11 @@
 
     // Disable global optimizations.
     internal.disableGlobalOptimizations();
-    internal.apiModelingOptions().disableApiCallerIdentification();
-    internal.apiModelingOptions().disableOutliningAndStubbing();
+    internal
+        .apiModelingOptions()
+        .disableApiCallerIdentification()
+        .disableOutlining()
+        .disableStubbingOfClasses();
 
     internal.setDumpInputFlags(getDumpInputFlags());
     internal.dumpOptions = dumpOptions();
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 1baf054..3741cb5 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -412,7 +412,7 @@
         assert ArtProfileCompletenessChecker.verify(appView);
         appView.rootSet().checkAllRulesAreUsed(options);
 
-        if (options.apiModelingOptions().reportUnknownApiReferences) {
+        if (options.apiModelingOptions().isReportUnknownApiReferencesEnabled()) {
           appView.apiLevelCompute().reportUnknownApiReferences();
         }
 
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 4b1738b..11577a1 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -1359,8 +1359,11 @@
     internal.outputInspections = InspectorImpl.wrapInspections(getOutputInspections());
 
     if (!enableMissingLibraryApiModeling) {
-      internal.apiModelingOptions().disableApiCallerIdentification();
-      internal.apiModelingOptions().disableOutliningAndStubbing();
+      internal
+          .apiModelingOptions()
+          .disableApiCallerIdentification()
+          .disableOutlining()
+          .disableStubbingOfClasses();
     }
 
     // Default is to remove all javac generated assertion code when generating DEX.
@@ -1382,7 +1385,7 @@
       internal.desugarState = DesugarState.OFF;
       // TODO(b/333477035): Since D8 dexing now supports outline/stubbing API calls R8/CF should
       //  likely disable API caller identification too so as not to prevent inlining.
-      internal.apiModelingOptions().disableOutliningAndStubbing();
+      internal.apiModelingOptions().disableOutlining().disableStubbingOfClasses();
     }
 
     // EXPERIMENTAL flags.
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 bca00e0..7c4dc03 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelCompute.java
@@ -66,7 +66,7 @@
   }
 
   public static AndroidApiLevelCompute create(AppView<?> appView) {
-    return appView.options().apiModelingOptions().enableLibraryApiModeling
+    return appView.options().apiModelingOptions().isApiModelingEnabled()
         ? new DefaultAndroidApiLevelCompute(appView)
         : noAndroidApiLevelCompute();
   }
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiModelingOptions.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiModelingOptions.java
index 4c0280b..1c2f763 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiModelingOptions.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiModelingOptions.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.references.FieldReference;
 import com.android.tools.r8.references.MethodReference;
 import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.ZipUtils;
 import java.nio.file.Paths;
@@ -24,7 +25,7 @@
 
   // Flag to specify if we should load the database or not. The api database is used for
   // library member rebinding.
-  public boolean enableLibraryApiModeling =
+  private boolean enableLibraryApiModeling =
       System.getProperty("com.android.tools.r8.disableApiModeling") == null;
 
   // Flag to specify Android extension libraries (also known as OEM-implemented shared libraries
@@ -34,7 +35,43 @@
   public String androidApiExtensionLibraries =
       System.getProperty("com.android.tools.r8.androidApiExtensionLibraries");
 
+  // TODO(b/326252366): Remove support for list of extension packages in favour of only
+  //  supporting passing extension libraries as JAR files.
+  // Flag to specify packages for Android extension APIs (also known as OEM-implemented
+  // shared libraries or sidecars). The packages are specified as java package names
+  // separated by commas. All APIs within these packages are handled as having an API level
+  // higher than any existing API level as these APIs might not exist on any device independent
+  // of API level (the nature of an extension API).
+  // TODO(b/326252366): This mechanism should be extended to also specify the extension for
+  //  each package to prevent merging of API outline methods fron different extensions.
+  public String androidApiExtensionPackages =
+      System.getProperty("com.android.tools.r8.androidApiExtensionPackages");
+
+  // The flag enableApiCallerIdentification controls if we can inline or merge targets with
+  // different api levels. It is also the flag that specifies if we assign api levels to
+  // references.
+  private boolean enableApiCallerIdentification = true;
+  private boolean enableStubbingOfClasses = true;
+  private boolean enableOutliningOfMethods = true;
+  private boolean checkAllApiReferencesAreSet = true;
+
+  // TODO(b/232823652): Enable when we can compute the offset correctly.
+  public boolean useMemoryMappedByteBuffer = false;
+
+  // A mapping from references to the api-level introducing them.
+  public Map<MethodReference, AndroidApiLevel> methodApiMapping = new HashMap<>();
+  public Map<FieldReference, AndroidApiLevel> fieldApiMapping = new HashMap<>();
+  public Map<ClassReference, AndroidApiLevel> classApiMapping = new HashMap<>();
+  public BiConsumer<MethodReference, ComputedApiLevel> tracedMethodApiLevelCallback = null;
+
+  private final InternalOptions options;
+
+  public AndroidApiModelingOptions(InternalOptions options) {
+    this.options = options;
+  }
+
   public void forEachAndroidApiExtensionClassDescriptor(Consumer<String> consumer) {
+    assert isApiModelingEnabled();
     if (androidApiExtensionLibraries != null) {
       StringUtils.split(androidApiExtensionLibraries, ',')
           .forEach(
@@ -54,100 +91,93 @@
     }
   }
 
-  // TODO(b/326252366): Remove support for list of extension packages in favour of only
-  //  supporting passing extension libraries as JAR files.
-  // Flag to specify packages for Android extension APIs (also known as OEM-implemented
-  // shared libraries or sidecars). The packages are specified as java package names
-  // separated by commas. All APIs within these packages are handled as having an API level
-  // higher than any existing API level as these APIs might not exist on any device independent
-  // of API level (the nature of an extension API).
-  // TODO(b/326252366): This mechanism should be extended to also specify the extension for
-  //  each package to prevent merging of API outline methods fron different extensions.
-  public String androidApiExtensionPackages =
-      System.getProperty("com.android.tools.r8.androidApiExtensionPackages");
-
   public void forEachAndroidApiExtensionPackage(Consumer<String> consumer) {
+    assert isApiModelingEnabled();
     if (androidApiExtensionPackages != null) {
       StringUtils.split(androidApiExtensionPackages, ',').forEach(consumer);
     }
   }
 
-  // The flag enableApiCallerIdentification controls if we can inline or merge targets with
-  // different api levels. It is also the flag that specifies if we assign api levels to
-  // references.
-  public boolean enableApiCallerIdentification =
-      System.getProperty("com.android.tools.r8.disableApiModeling") == null;
-  public boolean checkAllApiReferencesAreSet =
-      System.getProperty("com.android.tools.r8.disableApiModeling") == null;
-  public boolean enableStubbingOfClasses =
-      System.getProperty("com.android.tools.r8.disableApiModeling") == null;
-  public boolean enableOutliningOfMethods =
-      System.getProperty("com.android.tools.r8.disableApiModeling") == null;
-  public boolean reportUnknownApiReferences =
-      System.getProperty("com.android.tools.r8.reportUnknownApiReferences") != null;
-
-  // TODO(b/232823652): Enable when we can compute the offset correctly.
-  public boolean useMemoryMappedByteBuffer = false;
-
-  // A mapping from references to the api-level introducing them.
-  public Map<MethodReference, AndroidApiLevel> methodApiMapping = new HashMap<>();
-  public Map<FieldReference, AndroidApiLevel> fieldApiMapping = new HashMap<>();
-  public Map<ClassReference, AndroidApiLevel> classApiMapping = new HashMap<>();
-  public BiConsumer<MethodReference, ComputedApiLevel> tracedMethodApiLevelCallback = null;
-
-  public void visitMockedApiLevelsForReferences(
-      DexItemFactory factory, BiConsumer<DexReference, AndroidApiLevel> apiLevelConsumer) {
-    if (methodApiMapping.isEmpty() && fieldApiMapping.isEmpty() && classApiMapping.isEmpty()) {
-      return;
-    }
-    classApiMapping.forEach(
-        (classReference, apiLevel) -> {
-          apiLevelConsumer.accept(factory.createType(classReference.getDescriptor()), apiLevel);
-        });
-    fieldApiMapping.forEach(
-        (fieldReference, apiLevel) -> {
-          apiLevelConsumer.accept(factory.createField(fieldReference), apiLevel);
-        });
-    methodApiMapping.forEach(
-        (methodReference, apiLevel) -> {
-          apiLevelConsumer.accept(factory.createMethod(methodReference), apiLevel);
-        });
-  }
-
-  public boolean isApiLibraryModelingEnabled() {
+  public boolean isApiModelingEnabled() {
+    // TODO(b/384426376): Should return false when compiling to CF.
     return enableLibraryApiModeling;
   }
 
-  public boolean isCheckAllApiReferencesAreSet() {
-    return enableLibraryApiModeling && checkAllApiReferencesAreSet;
-  }
-
   public boolean isApiCallerIdentificationEnabled() {
-    return enableLibraryApiModeling && enableApiCallerIdentification;
+    return isApiModelingEnabled() && enableApiCallerIdentification;
   }
 
-  public void disableApiModeling() {
-    enableLibraryApiModeling = false;
-    enableApiCallerIdentification = false;
-    enableOutliningOfMethods = false;
-    enableStubbingOfClasses = false;
-    checkAllApiReferencesAreSet = false;
+  public boolean isStubbingOfClassesEnabled() {
+    // TODO(b/384426376): Should not check backend when isApiModelingEnabled() return false for CF.
+    return isApiModelingEnabled() && options.isGeneratingDex() && enableStubbingOfClasses;
   }
 
-  /**
-   * Disable the workarounds for missing APIs. This does not disable the use of the database, just
-   * the introduction of soft-verification workarounds for potentially missing API references.
-   */
-  public void disableOutliningAndStubbing() {
-    enableOutliningOfMethods = false;
-    enableStubbingOfClasses = false;
+  public boolean isOutliningOfMethodsEnabled() {
+    // TODO(b/384426376): Should not check backend when isApiModelingEnabled() return false for CF.
+    return isApiModelingEnabled() && options.isGeneratingDex() && enableOutliningOfMethods;
   }
 
-  public void disableApiCallerIdentification() {
-    enableApiCallerIdentification = false;
+  public boolean isCheckAllApiReferencesAreSet() {
+    return isApiModelingEnabled() && checkAllApiReferencesAreSet;
   }
 
-  public void disableStubbingOfClasses() {
-    enableStubbingOfClasses = false;
+  public boolean isReportUnknownApiReferencesEnabled() {
+    return isApiModelingEnabled()
+        && System.getProperty("com.android.tools.r8.reportUnknownApiReferences") != null;
+  }
+
+  public AndroidApiModelingOptions disableApiModeling() {
+    return setEnableApiModeling(false);
+  }
+
+  public AndroidApiModelingOptions setEnableApiModeling(boolean value) {
+    enableLibraryApiModeling = value;
+    return this;
+  }
+
+  public AndroidApiModelingOptions disableApiCallerIdentification() {
+    return setEnableApiCallerIdentification(false);
+  }
+
+  public AndroidApiModelingOptions setEnableApiCallerIdentification(boolean value) {
+    enableApiCallerIdentification = value;
+    return this;
+  }
+
+  public AndroidApiModelingOptions disableOutlining() {
+    return setEnableOutliningOfMethods(false);
+  }
+
+  public AndroidApiModelingOptions setEnableOutliningOfMethods(boolean value) {
+    enableOutliningOfMethods = value;
+    return this;
+  }
+
+  public AndroidApiModelingOptions disableStubbingOfClasses() {
+    return setEnableStubbingOfClasses(false);
+  }
+
+  public AndroidApiModelingOptions setEnableStubbingOfClasses(boolean value) {
+    enableStubbingOfClasses = value;
+    return this;
+  }
+
+  public AndroidApiModelingOptions setCheckAllApiReferencesAreSet(boolean value) {
+    checkAllApiReferencesAreSet = value;
+    return this;
+  }
+
+  public void visitMockedApiLevelsForReferences(
+      DexItemFactory factory, BiConsumer<DexReference, AndroidApiLevel> apiLevelConsumer) {
+    assert isApiModelingEnabled();
+    classApiMapping.forEach(
+        (classReference, apiLevel) ->
+            apiLevelConsumer.accept(factory.createType(classReference.getDescriptor()), apiLevel));
+    fieldApiMapping.forEach(
+        (fieldReference, apiLevel) ->
+            apiLevelConsumer.accept(factory.createField(fieldReference), apiLevel));
+    methodApiMapping.forEach(
+        (methodReference, apiLevel) ->
+            apiLevelConsumer.accept(factory.createMethod(methodReference), apiLevel));
   }
 }
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
index fc51eb0..69c2591 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
@@ -38,12 +38,13 @@
     androidApiLevelDatabase =
         new AndroidApiLevelHashingDatabaseImpl(
             predefinedApiTypeLookupForHashing, appView.options(), appView.reporter());
-    reportUnknownReferences = appView.options().apiModelingOptions().reportUnknownApiReferences;
+    reportUnknownReferences =
+        appView.options().apiModelingOptions().isReportUnknownApiReferencesEnabled();
   }
 
   public static AndroidApiReferenceLevelCache create(
       AppView<?> appView, AndroidApiLevelCompute apiLevelCompute) {
-    assert appView.options().apiModelingOptions().isApiLibraryModelingEnabled();
+    assert appView.options().apiModelingOptions().isApiModelingEnabled();
     ImmutableList.Builder<AndroidApiForHashingReference> builder = ImmutableList.builder();
     BiConsumer<DexReference, AndroidApiLevel> addItemToList =
         ConsumerUtils.andThen(AndroidApiForHashingReference::create, builder::add);
diff --git a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
index f663fd4..110a167 100644
--- a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
+++ b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
@@ -63,8 +63,7 @@
   }
 
   public void run(ExecutorService executorService) throws ExecutionException {
-    if (appView.options().isGeneratingDex()
-        && appView.options().apiModelingOptions().enableStubbingOfClasses) {
+    if (appView.options().apiModelingOptions().isStubbingOfClassesEnabled()) {
       Collection<DexProgramClass> classes =
           ListUtils.filter(
               appView.appInfo().classes(), DexProgramClass::originatesFromClassResource);
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index bdea90a..c097769 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -279,7 +279,7 @@
     return builder(this)
         .setField(field)
         .disableAndroidApiLevelCheckIf(
-            !appView.options().apiModelingOptions().enableApiCallerIdentification
+            !appView.options().apiModelingOptions().isApiCallerIdentificationEnabled()
                 || !appView.enableWholeProgramOptimizations())
         .apply(consumer)
         .build();
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 9e7ec82..d60a682 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -1368,7 +1368,7 @@
     if (from.hasClassFileVersion()) {
       upgradeClassFileVersion(from.getClassFileVersion());
     }
-    if (appView.options().apiModelingOptions().enableApiCallerIdentification
+    if (appView.options().apiModelingOptions().isApiCallerIdentificationEnabled()
         && appView.enableWholeProgramOptimizations()) {
       apiLevelForCode = getApiLevelForCode().max(from.getApiLevelForCode());
     }
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/ApiModelAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/ApiModelAnalysis.java
index 4b6337e..74100f0 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/ApiModelAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/ApiModelAnalysis.java
@@ -40,7 +40,7 @@
   public static void register(
       AppView<? extends AppInfoWithClassHierarchy> appView,
       EnqueuerAnalysisCollection.Builder builder) {
-    if (appView.options().apiModelingOptions().enableLibraryApiModeling) {
+    if (appView.options().apiModelingOptions().isApiModelingEnabled()) {
       ApiModelAnalysis analysis = new ApiModelAnalysis(appView);
       builder
           .addNewlyFailedMethodResolutionAnalysis(analysis)
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
index 3499c30..6d88029 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/ClassMerger.java
@@ -134,7 +134,7 @@
     lensBuilder.recordNewMethodSignature(syntheticMethodReference, newMethodReference, true);
 
     ComputedApiLevel apiReferenceLevel =
-        appView.options().apiModelingOptions().isApiLibraryModelingEnabled()
+        appView.options().apiModelingOptions().isApiModelingEnabled()
             ? classInitializerMerger.getApiReferenceLevel(appView)
             : ComputedApiLevel.notSet();
     DexEncodedMethod definition =
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index f626f7b..433f6f0 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -211,7 +211,7 @@
             ? CfInstructionDesugaringCollection.empty()
             : CfInstructionDesugaringCollection.create(appView, appView.apiLevelCompute());
     removeVerificationErrorForUnknownReturnedValues =
-        (appView.options().apiModelingOptions().enableLibraryApiModeling
+        (appView.options().apiModelingOptions().isApiModelingEnabled()
                 && appView.options().canHaveVerifyErrorForUnknownUnusedReturnValue())
             ? new RemoveVerificationErrorForUnknownReturnedValues(appView)
             : null;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index 5aa1c3f..eda2b3d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -74,8 +74,7 @@
     if (alwaysThrowingInstructionDesugaring != null) {
       desugarings.add(alwaysThrowingInstructionDesugaring);
     }
-    if (appView.options().apiModelingOptions().enableOutliningOfMethods) {
-      assert appView.options().isGeneratingDex();
+    if (appView.options().apiModelingOptions().isOutliningOfMethodsEnabled()) {
       yieldingDesugarings.add(new ApiInvokeOutlinerDesugaring(appView, apiLevelCompute));
     }
     if (appView.options().desugarState.isOff()) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/api/InstanceInitializerOutliner.java b/src/main/java/com/android/tools/r8/ir/optimize/api/InstanceInitializerOutliner.java
index a8abce9..17676ef 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/api/InstanceInitializerOutliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/api/InstanceInitializerOutliner.java
@@ -288,7 +288,7 @@
   @Override
   protected boolean shouldRewriteCode(IRCode code, MethodProcessor methodProcessor) {
     if (!appView.options().desugarState.isOn()
-        || !appView.options().apiModelingOptions().enableOutliningOfMethods
+        || !appView.options().apiModelingOptions().isOutliningOfMethodsEnabled()
         || !appView.options().getMinApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.L)) {
       return false;
     }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingMetadataImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingMetadataImpl.java
index 4f252c3..9d5476b 100644
--- a/src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingMetadataImpl.java
+++ b/src/main/java/com/android/tools/r8/metadata/impl/D8ApiModelingMetadataImpl.java
@@ -24,7 +24,7 @@
   private D8ApiModelingMetadataImpl() {}
 
   public static D8ApiModelingMetadataImpl create(InternalOptions options) {
-    return options.apiModelingOptions().enableLibraryApiModeling
+    return options.apiModelingOptions().isApiModelingEnabled()
         ? new D8ApiModelingMetadataImpl()
         : null;
   }
diff --git a/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingMetadataImpl.java b/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingMetadataImpl.java
index 28f388a..b79c934 100644
--- a/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingMetadataImpl.java
+++ b/src/main/java/com/android/tools/r8/metadata/impl/R8ApiModelingMetadataImpl.java
@@ -24,7 +24,7 @@
   private R8ApiModelingMetadataImpl() {}
 
   public static R8ApiModelingMetadataImpl create(InternalOptions options) {
-    return options.apiModelingOptions().enableLibraryApiModeling
+    return options.apiModelingOptions().isApiModelingEnabled()
         ? new R8ApiModelingMetadataImpl()
         : null;
   }
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index c3d3f20..f16d405 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -230,7 +230,7 @@
                         if (!targetDefinition.isAbstract()
                             && targetDefinition.getApiLevelForCode().isNotSetApiLevel()) {
                           assert target.isLibraryMethod()
-                              || !appView.options().apiModelingOptions().enableLibraryApiModeling;
+                              || !appView.options().apiModelingOptions().isApiModelingEnabled();
                           builder.setApiLevelForCode(
                               appView
                                   .apiLevelCompute()
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 cf855e7..a3ee59e 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
@@ -150,10 +150,10 @@
       AndroidApiLevelCompute androidApiLevelCompute,
       InternalOptions options) {
     if (!androidApiLevelCompute.isEnabled()) {
-      assert !options.apiModelingOptions().enableLibraryApiModeling;
+      assert !options.apiModelingOptions().isApiModelingEnabled();
       return false;
     }
-    assert options.apiModelingOptions().enableLibraryApiModeling;
+    assert options.apiModelingOptions().isApiModelingEnabled();
     ComputedApiLevel apiLevel =
         androidApiLevelCompute.computeApiLevelForLibraryReference(
             method.getReference(), ComputedApiLevel.unknown());
@@ -199,7 +199,7 @@
       AndroidApiLevelCompute androidApiLevelCompute,
       InternalOptions options,
       DexItemFactory factory) {
-    if (!options.apiModelingOptions().isApiLibraryModelingEnabled()) {
+    if (!options.apiModelingOptions().isApiModelingEnabled()) {
       return factory.libraryTypesAssumedToBePresent.contains(definition.getContextType());
     }
     ComputedApiLevel apiLevel =
@@ -210,7 +210,7 @@
 
   private static boolean isApiSafeForReference(
       LibraryDefinition newDefinition, LibraryDefinition oldDefinition, AppView<?> appView) {
-    assert appView.options().apiModelingOptions().isApiLibraryModelingEnabled();
+    assert appView.options().apiModelingOptions().isApiModelingEnabled();
     assert !isApiSafeForReference(newDefinition, appView)
         : "Clients should first check if the definition is present on all apis since the min api";
     AndroidApiLevelCompute androidApiLevelCompute = appView.apiLevelCompute();
@@ -249,7 +249,7 @@
       // Program and classpath classes are not api level dependent.
       return true;
     }
-    if (!appView.options().apiModelingOptions().isApiLibraryModelingEnabled()) {
+    if (!appView.options().apiModelingOptions().isApiModelingEnabled()) {
       // Conservatively bail out if we don't have api modeling.
       return false;
     }
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 761511e..1025dc4 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1011,7 +1011,8 @@
       new RedundantBridgeRemovalOptions();
   private final KotlinOptimizationOptions kotlinOptimizationOptions =
       new KotlinOptimizationOptions();
-  private final AndroidApiModelingOptions apiModelTestingOptions = new AndroidApiModelingOptions();
+  private final AndroidApiModelingOptions apiModelTestingOptions =
+      new AndroidApiModelingOptions(this);
   private final DesugarSpecificOptions desugarSpecificOptions = new DesugarSpecificOptions();
   private final MappingComposeOptions mappingComposeOptions = new MappingComposeOptions();
   private final ArtProfileOptions artProfileOptions = new ArtProfileOptions(this);
diff --git a/src/test/examplesJava11/com/android/tools/r8/jdk11/desugar/nest/NestAttributesUpdateTest.java b/src/test/examplesJava11/com/android/tools/r8/jdk11/desugar/nest/NestAttributesUpdateTest.java
index 15e6b6a..95f06d8 100644
--- a/src/test/examplesJava11/com/android/tools/r8/jdk11/desugar/nest/NestAttributesUpdateTest.java
+++ b/src/test/examplesJava11/com/android/tools/r8/jdk11/desugar/nest/NestAttributesUpdateTest.java
@@ -67,7 +67,7 @@
                 internalOptions -> {
                   // The test makes an invoke to StringConcatFactory which is not known to DEX and
                   // we therefore fail to merge the classes.
-                  internalOptions.apiModelingOptions().enableApiCallerIdentification = false;
+                  internalOptions.apiModelingOptions().disableApiCallerIdentification();
                 }));
   }
 
diff --git a/src/test/java/com/android/tools/r8/R8CommandTest.java b/src/test/java/com/android/tools/r8/R8CommandTest.java
index ff9152b..215605d 100644
--- a/src/test/java/com/android/tools/r8/R8CommandTest.java
+++ b/src/test/java/com/android/tools/r8/R8CommandTest.java
@@ -1001,8 +1001,8 @@
   public void defaultApiModelingState() throws Exception {
     AndroidApiModelingOptions options = parse("").getInternalOptions().apiModelingOptions();
     assertTrue(options.isApiCallerIdentificationEnabled());
-    assertTrue(options.enableOutliningOfMethods);
-    assertTrue(options.enableStubbingOfClasses);
+    assertTrue(options.isOutliningOfMethodsEnabled());
+    assertTrue(options.isStubbingOfClassesEnabled());
   }
 
   @Test
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelManualOutlineWithUnknownReturnTypeTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelManualOutlineWithUnknownReturnTypeTest.java
index dd26dcd..ef54500 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelManualOutlineWithUnknownReturnTypeTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelManualOutlineWithUnknownReturnTypeTest.java
@@ -76,7 +76,7 @@
         .addLibraryClasses(LibraryClass.class, LibrarySub.class)
         .setMinApi(parameters)
         .addOptionsModification(
-            options -> options.apiModelingOptions().disableOutliningAndStubbing())
+            options -> options.apiModelingOptions().disableOutlining().disableStubbingOfClasses())
         .apply(setMockApiLevelForClass(LibraryClass.class, AndroidApiLevel.B))
         .apply(setMockApiLevelForClass(LibrarySub.class, getMockApiLevel()))
         .compile()
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 f369ed9..89dac07 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
@@ -46,101 +46,89 @@
 
   public static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
       ThrowableConsumer<T> setMockApiLevelForMethod(Method method, AndroidApiLevel apiLevel) {
-    return compilerBuilder -> {
-      compilerBuilder.addOptionsModification(
-          options -> {
-            options
-                .apiModelingOptions()
-                .methodApiMapping
-                .put(Reference.methodFromMethod(method), apiLevel);
-          });
-    };
+    return compilerBuilder ->
+        compilerBuilder.addOptionsModification(
+            options ->
+                options
+                    .apiModelingOptions()
+                    .methodApiMapping
+                    .put(Reference.methodFromMethod(method), apiLevel));
   }
 
   public static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
       ThrowableConsumer<T> setMockApiLevelForMethod(
           MethodReference method, AndroidApiLevel apiLevel) {
-    return compilerBuilder -> {
-      compilerBuilder.addOptionsModification(
-          options -> {
-            options.apiModelingOptions().methodApiMapping.put(method, apiLevel);
-          });
-    };
+    return compilerBuilder ->
+        compilerBuilder.addOptionsModification(
+            options -> options.apiModelingOptions().methodApiMapping.put(method, apiLevel));
   }
 
   public static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
       ThrowableConsumer<T> setMockApiLevelForMethod(
           Constructor<?> constructor, AndroidApiLevel apiLevel) {
-    return compilerBuilder -> {
-      compilerBuilder.addOptionsModification(
-          options -> {
-            options
-                .apiModelingOptions()
-                .methodApiMapping
-                .put(Reference.methodFromMethod(constructor), apiLevel);
-          });
-    };
+    return compilerBuilder ->
+        compilerBuilder.addOptionsModification(
+            options ->
+                options
+                    .apiModelingOptions()
+                    .methodApiMapping
+                    .put(Reference.methodFromMethod(constructor), apiLevel));
   }
 
   static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
       ThrowableConsumer<T> setMockApiLevelForDefaultInstanceInitializer(
           Class<?> clazz, AndroidApiLevel apiLevel) {
-    return compilerBuilder -> {
-      compilerBuilder.addOptionsModification(
-          options -> {
-            options
-                .apiModelingOptions()
-                .methodApiMapping
-                .put(
-                    Reference.method(
-                        Reference.classFromClass(clazz), "<init>", ImmutableList.of(), null),
-                    apiLevel);
-          });
-    };
+    return compilerBuilder ->
+        compilerBuilder.addOptionsModification(
+            options ->
+                options
+                    .apiModelingOptions()
+                    .methodApiMapping
+                    .put(
+                        Reference.method(
+                            Reference.classFromClass(clazz), "<init>", ImmutableList.of(), null),
+                        apiLevel));
   }
 
   static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
       ThrowableConsumer<T> setMockApiLevelForField(Field field, AndroidApiLevel apiLevel) {
-    return compilerBuilder -> {
-      compilerBuilder.addOptionsModification(
-          options -> {
-            options
-                .apiModelingOptions()
-                .fieldApiMapping
-                .put(Reference.fieldFromField(field), apiLevel);
-          });
-    };
+    return compilerBuilder ->
+        compilerBuilder.addOptionsModification(
+            options ->
+                options
+                    .apiModelingOptions()
+                    .fieldApiMapping
+                    .put(Reference.fieldFromField(field), apiLevel));
   }
 
   public static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
       ThrowableConsumer<T> setMockApiLevelForClass(Class<?> clazz, AndroidApiLevel apiLevel) {
     return compilerBuilder -> {
       compilerBuilder.addOptionsModification(
-          options -> {
-            options
-                .apiModelingOptions()
-                .classApiMapping
-                .put(Reference.classFromClass(clazz), apiLevel);
-          });
+          options ->
+              options
+                  .apiModelingOptions()
+                  .classApiMapping
+                  .put(Reference.classFromClass(clazz), apiLevel));
     };
   }
 
   public static void enableApiCallerIdentification(
       TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     compilerBuilder.addOptionsModification(
-        options -> {
-          options.apiModelingOptions().enableLibraryApiModeling = true;
-          options.apiModelingOptions().enableApiCallerIdentification = true;
-        });
+        options ->
+            options
+                .apiModelingOptions()
+                .setEnableApiModeling(true)
+                .setEnableApiCallerIdentification(true));
   }
 
   public static void enableStubbingOfClassesAndDisableGlobalSyntheticCheck(
       TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     compilerBuilder.addOptionsModification(
         options -> {
+          options.apiModelingOptions().setEnableApiModeling(true).setEnableStubbingOfClasses(true);
           if (options.isGeneratingDex()) {
-            options.apiModelingOptions().enableLibraryApiModeling = true;
-            options.apiModelingOptions().enableStubbingOfClasses = true;
             // Our tests rely on us amending the library path with additional classes that are not
             // in the library.
             options.testing.globalSyntheticCreatedCallback = null;
@@ -150,31 +138,30 @@
 
   public static void enableStubbingOfClasses(TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     compilerBuilder.addOptionsModification(
-        options -> {
-          if (options.isGeneratingDex()) {
-            options.apiModelingOptions().enableLibraryApiModeling = true;
-            options.apiModelingOptions().enableStubbingOfClasses = true;
-          }
-        });
+        options ->
+            options
+                .apiModelingOptions()
+                .setEnableApiModeling(true)
+                .setEnableStubbingOfClasses(true));
   }
 
   public static void enableOutliningOfMethods(TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     compilerBuilder.addOptionsModification(
-        options -> {
-          if (options.isGeneratingDex()) {
-            options.apiModelingOptions().enableLibraryApiModeling = true;
-            options.apiModelingOptions().enableOutliningOfMethods = true;
-          }
-        });
+        options ->
+            options
+                .apiModelingOptions()
+                .setEnableApiModeling(true)
+                .setEnableOutliningOfMethods(true));
   }
 
   static void disableCheckAllApiReferencesAreNotUnknown(
       TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     compilerBuilder.addOptionsModification(
-        options -> {
-          options.apiModelingOptions().enableApiCallerIdentification = true;
-          options.apiModelingOptions().checkAllApiReferencesAreSet = false;
-        });
+        options ->
+            options
+                .apiModelingOptions()
+                .setEnableApiCallerIdentification(true)
+                .setCheckAllApiReferencesAreSet(false));
   }
 
   public static void disableOutliningAndStubbing(
@@ -185,25 +172,25 @@
 
   public static void disableStubbingOfClasses(TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     compilerBuilder.addOptionsModification(
-        options -> options.apiModelingOptions().enableStubbingOfClasses = false);
+        options -> options.apiModelingOptions().disableStubbingOfClasses());
   }
 
   public static void disableOutlining(TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     compilerBuilder.addOptionsModification(
-        options -> options.apiModelingOptions().enableOutliningOfMethods = false);
+        options -> options.apiModelingOptions().disableOutlining());
   }
 
   public static void disableApiCallerIdentification(
       TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     compilerBuilder.addOptionsModification(
-        options -> options.apiModelingOptions().enableApiCallerIdentification = false);
+        options -> options.apiModelingOptions().disableApiCallerIdentification());
   }
 
   public static void disableApiModeling(TestCompilerBuilder<?, ?, ?, ?, ?> compilerBuilder) {
     disableOutliningAndStubbing(compilerBuilder);
     disableApiCallerIdentification(compilerBuilder);
     compilerBuilder.addOptionsModification(
-        options -> options.apiModelingOptions().enableLibraryApiModeling = false);
+        options -> options.apiModelingOptions().disableApiModeling());
   }
 
   static <T extends TestCompilerBuilder<?, ?, ?, ?, ?>>
@@ -213,13 +200,12 @@
       compilerBuilder.addOptionsModification(
           options -> {
             options.apiModelingOptions().tracedMethodApiLevelCallback =
-                (methodReference, computedApiLevel) -> {
-                  consumer.accept(
-                      methodReference,
-                      computedApiLevel.isKnownApiLevel()
-                          ? computedApiLevel.asKnownApiLevel().getApiLevel()
-                          : null);
-                };
+                (methodReference, computedApiLevel) ->
+                    consumer.accept(
+                        methodReference,
+                        computedApiLevel.isKnownApiLevel()
+                            ? computedApiLevel.asKnownApiLevel().getApiLevel()
+                            : null);
           });
     };
   }
@@ -241,7 +227,7 @@
   }
 
   static ApiModelingMethodVerificationHelper verifyThat(
-      CodeInspector inspector, TestParameters parameters, Constructor method) {
+      CodeInspector inspector, TestParameters parameters, Constructor<?> method) {
     return new ApiModelingMethodVerificationHelper(
         inspector, parameters, Reference.methodFromMethod(method));
   }