New feature flag to disable build config

android.features.buildConfig = false disables
generation and packaging of build config in all
module types.

The long deprecated android.packageBuildConfig is
removed.

Update ProductFlavor/BuildType to receive DslScope
instead of its content as separate params.
Calling buildConfigField on them with the feature
disable throws an error.

Fixes: 72050365
Test: new integ test.
Change-Id: I4fd931ae3008091de641d3d7bdbc935d7932d62d
diff --git a/build-system/gradle-api/src/main/java/com/android/build/api/dsl/BuildFeatures.kt b/build-system/gradle-api/src/main/java/com/android/build/api/dsl/BuildFeatures.kt
index 29f8f99..f1a253a 100644
--- a/build-system/gradle-api/src/main/java/com/android/build/api/dsl/BuildFeatures.kt
+++ b/build-system/gradle-api/src/main/java/com/android/build/api/dsl/BuildFeatures.kt
@@ -32,4 +32,17 @@
      * More information available about this feature at: TBD
      **/
     var compose: Boolean?
+
+    /**
+     * Flag to enable/disable generation of the BuildConfig class.
+     *
+     * Setting the value to null resets to the default value.
+     *
+     * The default value can be set with the gradle property android.defaults.buildfeatures.buildconfig
+     * This affects all modules.
+     * Default value is true
+     *
+     * More information about this feature at: TBD
+     */
+    var buildConfig: Boolean?
 }
\ No newline at end of file
diff --git a/build-system/gradle-api/src/test/resources/com/android/build/api/incubating-api.txt b/build-system/gradle-api/src/test/resources/com/android/build/api/incubating-api.txt
index 2ea4956..3f8fc5b 100644
--- a/build-system/gradle-api/src/test/resources/com/android/build/api/incubating-api.txt
+++ b/build-system/gradle-api/src/test/resources/com/android/build/api/incubating-api.txt
@@ -4,7 +4,7 @@
 below are backwards compatible.
 -------------------------------------------------------------------------
 Sha256 of below classes:
-f8037d4ea0da1d7918335286325df7ba867dbdd1eb604533f6e28b508b693c9c
+c4506f505d0029cf4c881af895f6329dff60dffeb88d53c08ef1e204e37b2c3c
 -------------------------------------------------------------------------
 com.android.build.api.artifact.AppendRequest
 com.android.build.api.artifact.AppendRequest.on: com.android.build.api.artifact.AppendRequest<FILE_TYPE> (ARTIFACT_TYPE)
@@ -55,7 +55,9 @@
 com.android.build.api.dsl.ApkExtension
 com.android.build.api.dsl.ApplicationExtension implements com.android.build.api.dsl.CommonExtension, com.android.build.api.dsl.ApkExtension, com.android.build.api.dsl.TestedExtension
 com.android.build.api.dsl.BuildFeatures
+com.android.build.api.dsl.BuildFeatures.getBuildConfig: java.lang.Boolean ()
 com.android.build.api.dsl.BuildFeatures.getCompose: java.lang.Boolean ()
+com.android.build.api.dsl.BuildFeatures.setBuildConfig: void (java.lang.Boolean)
 com.android.build.api.dsl.BuildFeatures.setCompose: void (java.lang.Boolean)
 com.android.build.api.dsl.CommonExtension
 com.android.build.api.dsl.DynamicFeatureExtension implements com.android.build.api.dsl.CommonExtension, com.android.build.api.dsl.ApkExtension, com.android.build.api.dsl.TestedExtension
diff --git a/build-system/gradle-core/lint_baseline.xml b/build-system/gradle-core/lint_baseline.xml
index 0589a0b..7ddfb35 100755
--- a/build-system/gradle-core/lint_baseline.xml
+++ b/build-system/gradle-core/lint_baseline.xml
@@ -1,44 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 3.6.0-dev">
+<issues format="5" by="lint 4.0.0-dev">
 
     <issue
         id="VisibleForTests"
         message="This method should only be accessed from tests or within private scope">
         <location
             file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.java"
-            line="600"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope">
-        <location
-            file="src/main/java/com/android/build/gradle/internal/dsl/BuildType.java"
-            line="128"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope">
-        <location
-            file="src/main/java/com/android/build/gradle/internal/dsl/BuildType.java"
-            line="128"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope">
-        <location
-            file="src/main/java/com/android/build/gradle/internal/dsl/BuildType.java"
-            line="131"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope">
-        <location
-            file="src/main/java/com/android/build/gradle/internal/dsl/BuildType.java"
-            line="131"/>
+            line="592"/>
     </issue>
 
     <issue
@@ -54,7 +22,7 @@
         message="This method should only be accessed from tests or within private scope">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/featuresplit/FeatureSetMetadataWriterTask.kt"
-            line="122"/>
+            line="123"/>
     </issue>
 
     <issue
@@ -62,7 +30,7 @@
         message="This method should only be accessed from tests or within private scope">
         <location
             file="src/main/java/com/android/build/gradle/internal/res/LinkApplicationAndroidResourcesTask.kt"
-            line="821"/>
+            line="759"/>
     </issue>
 
     <issue
@@ -70,7 +38,7 @@
         message="Use `Integer.valueOf(index)` instead">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
-            line="73"/>
+            line="72"/>
     </issue>
 
     <issue
@@ -78,7 +46,7 @@
         message="Use `Integer.valueOf(libraryList.size)` instead">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
-            line="86"/>
+            line="85"/>
     </issue>
 
     <issue
@@ -86,7 +54,7 @@
         message="Use `Integer.valueOf(origIndex)` instead">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
-            line="90"/>
+            line="89"/>
     </issue>
 
     <issue
@@ -94,7 +62,7 @@
         message="Use `Integer.valueOf(libraryDep.libraryIndex)` instead">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
-            line="95"/>
+            line="94"/>
     </issue>
 
     <issue
@@ -102,7 +70,7 @@
         message="Use `Integer.valueOf(depIndex)` instead">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
-            line="98"/>
+            line="97"/>
     </issue>
 
     <issue
@@ -110,7 +78,7 @@
         message="Use `Integer.valueOf(depIndex)` instead">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/BundleReportDependenciesTask.kt"
-            line="111"/>
+            line="110"/>
     </issue>
 
     <issue
@@ -118,7 +86,7 @@
         message="Use `Integer.valueOf(libraries.size)` instead">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/PerModuleReportDependenciesTask.kt"
-            line="84"/>
+            line="102"/>
     </issue>
 
     <issue
@@ -126,7 +94,7 @@
         message="Use `Integer.valueOf(1)` instead">
         <location
             file="src/main/java/com/android/build/gradle/internal/core/VariantConfiguration.java"
-            line="911"/>
+            line="850"/>
     </issue>
 
     <issue
@@ -134,7 +102,7 @@
         message="Use `Integer.valueOf(-1)` instead">
         <location
             file="src/main/java/com/android/build/gradle/internal/core/VariantConfiguration.java"
-            line="938"/>
+            line="877"/>
     </issue>
 
     <issue
@@ -214,7 +182,7 @@
         message="Do not compare java.io.File with `equals` or `==`: will not work correctly on case insensitive file systems! See `go/files-howto`.">
         <location
             file="src/main/java/com/android/build/gradle/internal/ide/DefaultAndroidProject.java"
-            line="357"/>
+            line="370"/>
     </issue>
 
     <issue
@@ -302,7 +270,7 @@
         message="Avoid using common ForkJoinPool, directly or indirectly (for example via CompletableFuture). It has a limited set of threads on some machines which leads to hangs. See `go/do-not-freeze`.">
         <location
             file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.java"
-            line="243"/>
+            line="245"/>
     </issue>
 
     <issue
@@ -310,7 +278,7 @@
         message="Avoid using common ForkJoinPool, directly or indirectly (for example via CompletableFuture). It has a limited set of threads on some machines which leads to hangs. See `go/do-not-freeze`.">
         <location
             file="src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.java"
-            line="379"/>
+            line="374"/>
     </issue>
 
     <issue
@@ -318,7 +286,7 @@
         message="Avoid using common ForkJoinPool, directly or indirectly (for example via CompletableFuture). It has a limited set of threads on some machines which leads to hangs. See `go/do-not-freeze`.">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/BundleToApkTask.kt"
-            line="101"/>
+            line="100"/>
     </issue>
 
     <issue
@@ -326,7 +294,7 @@
         message="Avoid using common ForkJoinPool, directly or indirectly (for example via CompletableFuture). It has a limited set of threads on some machines which leads to hangs. See `go/do-not-freeze`.">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/BundleToStandaloneApkTask.kt"
-            line="131"/>
+            line="130"/>
     </issue>
 
     <issue
@@ -342,7 +310,7 @@
         message="Avoid using new ForkJoinPool instances when possible. Prefer using the IntelliJ application pool via `com.intellij.openapi.application.Application#executeOnPooledThread`, or for the Android Gradle Plugin use `com.android.build.gradle.internal.tasks.Workers`. See `go/do-not-freeze`.">
         <location
             file="src/main/java/com/android/build/gradle/internal/res/namespaced/AutoNamespaceDependenciesTask.kt"
-            line="513"/>
+            line="509"/>
     </issue>
 
     <issue
@@ -350,7 +318,7 @@
         message="Avoid using new ForkJoinPool instances when possible. Prefer using the IntelliJ application pool via `com.intellij.openapi.application.Application#executeOnPooledThread`, or for the Android Gradle Plugin use `com.android.build.gradle.internal.tasks.Workers`. See `go/do-not-freeze`.">
         <location
             file="src/main/java/com/android/build/gradle/internal/tasks/DexMergingTask.kt"
-            line="404"/>
+            line="399"/>
     </issue>
 
     <issue
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/AndroidConfig.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/AndroidConfig.java
index 3df925a..dc4fdd0 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/AndroidConfig.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/AndroidConfig.java
@@ -602,9 +602,6 @@
     /** build outputs for all variants */
     Collection<BaseVariantOutput> getBuildOutputs();
 
-    /** Whether to package build config class file. */
-    Boolean getPackageBuildConfig();
-
     /** Aidl files to package in the aar. */
     Collection<String> getAidlPackageWhiteList();
 
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/BaseExtension.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/BaseExtension.java
index 81d6343..e2c8a7d 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/BaseExtension.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/BaseExtension.java
@@ -228,9 +228,7 @@
                         DefaultConfig.class,
                         BuilderConstants.MAIN,
                         project,
-                        objectFactory,
-                        extraModelInfo.getDeprecationReporter(),
-                        project.getLogger());
+                        globalScope.getDslScope());
 
         aaptOptions =
                 objectFactory.newInstance(
@@ -1034,12 +1032,6 @@
         return testOptions;
     }
 
-    // For compatibility with LibraryExtension.
-    @Override
-    public Boolean getPackageBuildConfig() {
-        throw new GradleException("packageBuildConfig is not supported.");
-    }
-
     @Override
     public Collection<String> getAidlPackageWhiteList() {
         throw new GradleException("aidlPackageWhiteList is not supported.");
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/LibraryExtension.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/LibraryExtension.java
index f87fc61..2e0a477 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/LibraryExtension.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/LibraryExtension.java
@@ -33,8 +33,6 @@
     private final DefaultDomainObjectSet<LibraryVariant> libraryVariantList
             = new DefaultDomainObjectSet<LibraryVariant>(LibraryVariant.class);
 
-    private boolean packageBuildConfig = true;
-
     private Collection<String> aidlPackageWhiteList = null;
 
     public LibraryExtension(
@@ -92,26 +90,6 @@
         libraryVariantList.add((LibraryVariant) variant);
     }
 
-    public void packageBuildConfig(boolean value) {
-        if (!value) {
-            LoggingUtil.displayDeprecationWarning(logger, project,
-                    "Support for not packaging BuildConfig is deprecated.");
-        }
-
-        packageBuildConfig = value;
-    }
-
-    @Deprecated
-    public void setPackageBuildConfig(boolean value) {
-        // Remove when users stop requiring this setting.
-        packageBuildConfig(value);
-    }
-
-    @Override
-    public Boolean getPackageBuildConfig() {
-        return packageBuildConfig;
-    }
-
     public void aidlPackageWhiteList(String ... aidlFqcns) {
         if (aidlPackageWhiteList == null) {
             aidlPackageWhiteList = Lists.newArrayList();
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/LibraryTaskManager.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/LibraryTaskManager.java
index 57ca35a..aa4a975 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/LibraryTaskManager.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/LibraryTaskManager.java
@@ -299,7 +299,6 @@
         taskFactory.register(
                 new LibraryAarJarsTask.CreationAction(
                         variantScope,
-                        extension.getPackageBuildConfig(),
                         excludeDataBindingClassesIfNecessary(variantScope)));
 
 
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.java
index 24a1492..4b97ca0 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/TaskManager.java
@@ -951,11 +951,13 @@
     }
 
     public void createBuildConfigTask(@NonNull VariantScope scope) {
-        TaskProvider<GenerateBuildConfig> generateBuildConfigTask =
-                taskFactory.register(new GenerateBuildConfig.CreationAction(scope));
+        if (scope.getGlobalScope().getBuildFeatures().getBuildConfig()) {
+            TaskProvider<GenerateBuildConfig> generateBuildConfigTask =
+                    taskFactory.register(new GenerateBuildConfig.CreationAction(scope));
 
-        TaskFactoryUtils.dependsOn(
-                scope.getTaskContainer().getSourceGenTask(), generateBuildConfigTask);
+            TaskFactoryUtils.dependsOn(
+                    scope.getTaskContainer().getSourceGenTask(), generateBuildConfigTask);
+        }
     }
 
     public void createGenerateResValuesTask(
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BaseFlavor.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BaseFlavor.java
index 1da03a9..f352ee7 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BaseFlavor.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BaseFlavor.java
@@ -18,7 +18,7 @@
 
 import com.android.annotations.NonNull;
 import com.android.annotations.Nullable;
-import com.android.build.gradle.internal.errors.DeprecationReporter;
+import com.android.build.gradle.internal.api.dsl.DslScope;
 import com.android.builder.core.BuilderConstants;
 import com.android.builder.core.DefaultApiVersion;
 import com.android.builder.core.DefaultProductFlavor;
@@ -32,15 +32,13 @@
 import java.util.Set;
 import org.gradle.api.Action;
 import org.gradle.api.Project;
-import org.gradle.api.logging.Logger;
 import org.gradle.api.model.ObjectFactory;
 
 /** Base DSL object used to configure product flavors. */
 public abstract class BaseFlavor extends DefaultProductFlavor implements CoreProductFlavor {
 
     @NonNull protected final Project project;
-
-    @NonNull protected final Logger logger;
+    @NonNull private DslScope dslScope;
 
     @NonNull private final NdkOptions ndkConfig;
 
@@ -50,18 +48,11 @@
 
     @NonNull private final ShaderOptions shaderOptions;
 
-    @NonNull private final DeprecationReporter deprecationReporter;
-
-    public BaseFlavor(
-            @NonNull String name,
-            @NonNull Project project,
-            @NonNull ObjectFactory objectFactory,
-            @NonNull DeprecationReporter deprecationReporter,
-            @NonNull Logger logger) {
-        super(name, objectFactory.newInstance(VectorDrawablesOptions.class));
+    public BaseFlavor(@NonNull String name, @NonNull Project project, @NonNull DslScope dslScope) {
+        super(name, dslScope.getObjectFactory().newInstance(VectorDrawablesOptions.class));
         this.project = project;
-        this.deprecationReporter = deprecationReporter;
-        this.logger = logger;
+        this.dslScope = dslScope;
+        ObjectFactory objectFactory = dslScope.getObjectFactory();
         ndkConfig = objectFactory.newInstance(NdkOptions.class);
         externalNativeBuildOptions =
                 objectFactory.newInstance(ExternalNativeBuildOptions.class, objectFactory);
@@ -252,19 +243,21 @@
         if (alreadyPresent != null) {
             String flavorName = getName();
             if (BuilderConstants.MAIN.equals(flavorName)) {
-                logger.info(
-                        "DefaultConfig: buildConfigField '{}' value is being replaced: {} -> {}",
-                        name,
-                        alreadyPresent.getValue(),
-                        value);
+                dslScope.getLogger()
+                        .info(
+                                "DefaultConfig: buildConfigField '{}' value is being replaced: {} -> {}",
+                                name,
+                                alreadyPresent.getValue(),
+                                value);
             } else {
-                logger.info(
-                        "ProductFlavor({}): buildConfigField '{}' "
-                                + "value is being replaced: {} -> {}",
-                        flavorName,
-                        name,
-                        alreadyPresent.getValue(),
-                        value);
+                dslScope.getLogger()
+                        .info(
+                                "ProductFlavor({}): buildConfigField '{}' "
+                                        + "value is being replaced: {} -> {}",
+                                flavorName,
+                                name,
+                                alreadyPresent.getValue(),
+                                value);
             }
         }
         addBuildConfigField(new ClassFieldImpl(type, name, value));
@@ -288,18 +281,20 @@
         if (alreadyPresent != null) {
             String flavorName = getName();
             if (BuilderConstants.MAIN.equals(flavorName)) {
-                logger.info(
-                        "DefaultConfig: resValue '{}' value is being replaced: {} -> {}",
-                        name,
-                        alreadyPresent.getValue(),
-                        value);
+                dslScope.getLogger()
+                        .info(
+                                "DefaultConfig: resValue '{}' value is being replaced: {} -> {}",
+                                name,
+                                alreadyPresent.getValue(),
+                                value);
             } else {
-                logger.info(
-                        "ProductFlavor({}): resValue '{}' value is being replaced: {} -> {}",
-                        flavorName,
-                        name,
-                        alreadyPresent.getValue(),
-                        value);
+                dslScope.getLogger()
+                        .info(
+                                "ProductFlavor({}): resValue '{}' value is being replaced: {} -> {}",
+                                flavorName,
+                                name,
+                                alreadyPresent.getValue(),
+                                value);
             }
         }
         addResValue(new ClassFieldImpl(type, name, value));
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildFeaturesImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildFeaturesImpl.kt
index 763637e..25c1cbb 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildFeaturesImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildFeaturesImpl.kt
@@ -20,4 +20,6 @@
 
 open class BuildFeaturesImpl : BuildFeatures {
     override var compose: Boolean? = null
+
+    override var buildConfig: Boolean? = null
 }
\ No newline at end of file
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildType.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildType.java
index 2dd6f9d..560904a 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildType.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildType.java
@@ -19,16 +19,15 @@
 import com.android.annotations.NonNull;
 import com.android.annotations.Nullable;
 import com.android.build.gradle.api.JavaCompileOptions;
+import com.android.build.gradle.internal.api.dsl.DslScope;
 import com.android.build.gradle.internal.errors.DeprecationReporter;
 import com.android.build.gradle.internal.scope.CodeShrinker;
 import com.android.builder.core.BuilderConstants;
 import com.android.builder.core.DefaultBuildType;
-import com.android.builder.errors.EvalIssueReporter;
 import com.android.builder.errors.EvalIssueReporter.Type;
 import com.android.builder.internal.ClassFieldImpl;
 import com.android.builder.model.BaseConfig;
 import com.android.builder.model.ClassField;
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import java.io.Serializable;
@@ -72,13 +71,12 @@
     }
 
     @NonNull private final Project project;
+    @NonNull private DslScope dslScope;
     @NonNull private final NdkOptions ndkConfig;
     @NonNull private final ExternalNativeBuildOptions externalNativeBuildOptions;
     @NonNull
     private final com.android.build.gradle.internal.dsl.JavaCompileOptions javaCompileOptions;
     @NonNull private final ShaderOptions shaderOptions;
-    @NonNull private final EvalIssueReporter issueReporter;
-    @NonNull private final DeprecationReporter deprecationReporter;
     @NonNull private final PostProcessingBlock postProcessingBlock;
 
     @Nullable private PostProcessingConfiguration postProcessingConfiguration;
@@ -91,17 +89,12 @@
     private final Property<Boolean> isDefault;
 
     @Inject
-    public BuildType(
-            @NonNull String name,
-            @NonNull Project project,
-            @NonNull ObjectFactory objectFactory,
-            @NonNull EvalIssueReporter issueReporter,
-            @NonNull DeprecationReporter deprecationReporter) {
+    public BuildType(@NonNull String name, @NonNull Project project, @NonNull DslScope dslScope) {
         super(name);
         this.project = project;
-        this.issueReporter = issueReporter;
-        this.deprecationReporter = deprecationReporter;
+        this.dslScope = dslScope;
 
+        ObjectFactory objectFactory = dslScope.getObjectFactory();
         javaCompileOptions =
                 objectFactory.newInstance(
                         com.android.build.gradle.internal.dsl.JavaCompileOptions.class,
@@ -114,25 +107,6 @@
         isDefault = objectFactory.property(Boolean.class).convention(false);
     }
 
-    @VisibleForTesting
-    BuildType(
-            @NonNull String name,
-            @NonNull Project project,
-            @NonNull EvalIssueReporter issueReporter,
-            @NonNull DeprecationReporter deprecationReporter) {
-
-        super(name);
-        this.project = project;
-        this.issueReporter = issueReporter;
-        this.deprecationReporter = deprecationReporter;
-        javaCompileOptions = new com.android.build.gradle.internal.dsl.JavaCompileOptions();
-        shaderOptions = new ShaderOptions();
-        ndkConfig = new NdkOptions();
-        externalNativeBuildOptions = new ExternalNativeBuildOptions();
-        postProcessingBlock = new PostProcessingBlock(project);
-        isDefault = project.getObjects().property(Boolean.class).convention(false);
-    }
-
     private ImmutableList<String> matchingFallbacks;
 
     public void setMatchingFallbacks(String... fallbacks) {
@@ -324,7 +298,7 @@
                     String.format(
                             "BuildType(%s): buildConfigField '%s' value is being replaced: %s -> %s",
                             getName(), name, alreadyPresent.getValue(), value);
-            issueReporter.reportWarning(Type.GENERIC, message);
+            dslScope.getIssueReporter().reportWarning(Type.GENERIC, message);
         }
         addBuildConfigField(new ClassFieldImpl(type, name, value));
     }
@@ -350,7 +324,7 @@
                     String.format(
                             "BuildType(%s): resValue '%s' value is being replaced: %s -> %s",
                             getName(), name, alreadyPresent.getValue(), value);
-            issueReporter.reportWarning(Type.GENERIC, message);
+            dslScope.getIssueReporter().reportWarning(Type.GENERIC, message);
         }
         addResValue(new ClassFieldImpl(type, name, value));
     }
@@ -601,8 +575,9 @@
     public void setUseProguard(boolean useProguard) {
         checkPostProcessingConfiguration(PostProcessingConfiguration.OLD_DSL, "setUseProguard");
         if (dslChecksEnabled.get()) {
-            deprecationReporter.reportObsoleteUsage(
-                    "useProguard", DeprecationReporter.DeprecationTarget.DSL_USE_PROGUARD);
+            dslScope.getDeprecationReporter()
+                    .reportObsoleteUsage(
+                            "useProguard", DeprecationReporter.DeprecationTarget.DSL_USE_PROGUARD);
         }
     }
 
@@ -689,7 +664,7 @@
                 default:
                     throw new AssertionError("Unknown value " + used);
             }
-            issueReporter.reportError(Type.GENERIC, message, methodName);
+            dslScope.getIssueReporter().reportError(Type.GENERIC, message, methodName);
         }
     }
 
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildTypeFactory.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildTypeFactory.java
index 6917baf..491c866 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildTypeFactory.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/BuildTypeFactory.java
@@ -17,8 +17,7 @@
 package com.android.build.gradle.internal.dsl;
 
 import com.android.annotations.NonNull;
-import com.android.build.gradle.internal.errors.DeprecationReporter;
-import com.android.builder.errors.EvalIssueReporter;
+import com.android.build.gradle.internal.api.dsl.DslScope;
 import org.gradle.api.NamedDomainObjectFactory;
 import org.gradle.api.Project;
 import org.gradle.api.model.ObjectFactory;
@@ -28,24 +27,20 @@
 
     @NonNull private final ObjectFactory objectFactory;
     @NonNull private final Project project;
-    @NonNull private final EvalIssueReporter issueReporter;
-    @NonNull private final DeprecationReporter deprecationReporter;
+    @NonNull private DslScope dslScope;
 
     public BuildTypeFactory(
             @NonNull ObjectFactory objectFactory,
             @NonNull Project project,
-            @NonNull EvalIssueReporter issueReporter,
-            @NonNull DeprecationReporter deprecationReporter) {
+            @NonNull DslScope dslScope) {
         this.objectFactory = objectFactory;
         this.project = project;
-        this.issueReporter = issueReporter;
-        this.deprecationReporter = deprecationReporter;
+        this.dslScope = dslScope;
     }
 
     @NonNull
     @Override
     public BuildType create(@NonNull String name) {
-        return objectFactory.newInstance(
-                BuildType.class, name, project, objectFactory, issueReporter, deprecationReporter);
+        return objectFactory.newInstance(BuildType.class, name, project, dslScope);
     }
 }
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/DefaultConfig.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/DefaultConfig.java
index df37440..79ade24 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/DefaultConfig.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/DefaultConfig.java
@@ -17,22 +17,16 @@
 package com.android.build.gradle.internal.dsl;
 
 import com.android.annotations.NonNull;
-import com.android.build.gradle.internal.errors.DeprecationReporter;
+import com.android.build.gradle.internal.api.dsl.DslScope;
 import javax.inject.Inject;
 import org.gradle.api.Project;
-import org.gradle.api.logging.Logger;
-import org.gradle.api.model.ObjectFactory;
 
 /** DSL object for the defaultConfig object. */
 @SuppressWarnings({"WeakerAccess", "unused"}) // Exposed in the DSL.
 public class DefaultConfig extends BaseFlavor {
     @Inject
     public DefaultConfig(
-            @NonNull String name,
-            @NonNull Project project,
-            @NonNull ObjectFactory objectFactory,
-            @NonNull DeprecationReporter deprecationReporter,
-            @NonNull Logger logger) {
-        super(name, project, objectFactory, deprecationReporter, logger);
+            @NonNull String name, @NonNull Project project, @NonNull DslScope dslScope) {
+        super(name, project, dslScope);
     }
 }
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ProductFlavor.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ProductFlavor.java
index 15834ce..0d20b61 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ProductFlavor.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ProductFlavor.java
@@ -18,14 +18,12 @@
 
 import com.android.annotations.NonNull;
 import com.android.build.gradle.internal.VariantManager;
-import com.android.build.gradle.internal.errors.DeprecationReporter;
+import com.android.build.gradle.internal.api.dsl.DslScope;
 import com.android.builder.model.BaseConfig;
 import com.google.common.collect.ImmutableList;
 import java.util.List;
 import javax.inject.Inject;
 import org.gradle.api.Project;
-import org.gradle.api.logging.Logger;
-import org.gradle.api.model.ObjectFactory;
 import org.gradle.api.provider.Property;
 
 /**
@@ -63,13 +61,9 @@
 
     @Inject
     public ProductFlavor(
-            @NonNull String name,
-            @NonNull Project project,
-            @NonNull ObjectFactory objectFactory,
-            @NonNull DeprecationReporter deprecationReporter,
-            @NonNull Logger logger) {
-        super(name, project, objectFactory, deprecationReporter, logger);
-        isDefault = objectFactory.property(Boolean.class).convention(false);
+            @NonNull String name, @NonNull Project project, @NonNull DslScope dslScope) {
+        super(name, project, dslScope);
+        isDefault = dslScope.getObjectFactory().property(Boolean.class).convention(false);
     }
 
     private final Property<Boolean> isDefault;
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ProductFlavorFactory.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ProductFlavorFactory.java
index f2e7105..f7cf58d 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ProductFlavorFactory.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/dsl/ProductFlavorFactory.java
@@ -17,37 +17,30 @@
 package com.android.build.gradle.internal.dsl;
 
 import com.android.annotations.NonNull;
-import com.android.build.gradle.internal.errors.DeprecationReporter;
+import com.android.build.gradle.internal.api.dsl.DslScope;
 import org.gradle.api.NamedDomainObjectFactory;
 import org.gradle.api.Project;
-import org.gradle.api.logging.Logger;
 import org.gradle.api.model.ObjectFactory;
 
 /** Factory to create ProductFlavor object using an {@link ObjectFactory} to add the DSL methods. */
 public class ProductFlavorFactory implements NamedDomainObjectFactory<ProductFlavor> {
 
     @NonNull private final ObjectFactory objectFactory;
-    @NonNull
-    private final Project project;
-    @NonNull
-    private final Logger logger;
-    @NonNull private final DeprecationReporter deprecationReporter;
+    @NonNull private final Project project;
+    @NonNull private DslScope dslScope;
 
     public ProductFlavorFactory(
             @NonNull ObjectFactory objectFactory,
             @NonNull Project project,
-            @NonNull DeprecationReporter deprecationReporter,
-            @NonNull Logger logger) {
+            @NonNull DslScope dslScope) {
         this.objectFactory = objectFactory;
         this.project = project;
-        this.deprecationReporter = deprecationReporter;
-        this.logger = logger;
+        this.dslScope = dslScope;
     }
 
     @NonNull
     @Override
-    public ProductFlavor create(String name) {
-        return objectFactory.newInstance(
-                ProductFlavor.class, name, project, objectFactory, deprecationReporter, logger);
+    public ProductFlavor create(@NonNull String name) {
+        return objectFactory.newInstance(ProductFlavor.class, name, project, dslScope);
     }
 }
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.java
index 82ed21e..a28cf90 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/plugins/BasePlugin.java
@@ -399,19 +399,12 @@
         final NamedDomainObjectContainer<BuildType> buildTypeContainer =
                 project.container(
                         BuildType.class,
-                        new BuildTypeFactory(
-                                objectFactory,
-                                project,
-                                extraModelInfo.getSyncIssueHandler(),
-                                extraModelInfo.getDeprecationReporter()));
+                        new BuildTypeFactory(objectFactory, project, globalScope.getDslScope()));
         final NamedDomainObjectContainer<ProductFlavor> productFlavorContainer =
                 project.container(
                         ProductFlavor.class,
                         new ProductFlavorFactory(
-                                objectFactory,
-                                project,
-                                extraModelInfo.getDeprecationReporter(),
-                                project.getLogger()));
+                                objectFactory, project, globalScope.getDslScope()));
         final NamedDomainObjectContainer<SigningConfig> signingConfigContainer =
                 project.container(
                         SigningConfig.class,
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/BuildFeatureValues.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/BuildFeatureValues.kt
index 4de4764..0750fe4 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/BuildFeatureValues.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/BuildFeatureValues.kt
@@ -22,4 +22,5 @@
  */
 interface BuildFeatureValues {
     val jetpackCompose: Boolean
+    val buildConfig: Boolean
 }
\ No newline at end of file
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/BuildFeatureValuesImpl.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/BuildFeatureValuesImpl.kt
index 73bbc89..d77dc7e 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/BuildFeatureValuesImpl.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/BuildFeatureValuesImpl.kt
@@ -17,6 +17,7 @@
 package com.android.build.gradle.internal.scope
 
 import com.android.build.api.dsl.BuildFeatures
+import com.android.build.gradle.options.BooleanOption
 import com.android.build.gradle.options.ProjectOptions
 
 class BuildFeatureValuesImpl(
@@ -29,4 +30,7 @@
 
     override val jetpackCompose: Boolean
         get() = dslBuildFeatures.compose ?: false
+
+    override val buildConfig: Boolean
+        get() = dslBuildFeatures.buildConfig ?: projectOptions[BooleanOption.BUILD_FEATURE_BUILDCONFIG]
 }
\ No newline at end of file
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryClasses.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryClasses.kt
index 811284f..9f665f9 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryClasses.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/BundleLibraryClasses.kt
@@ -65,10 +65,6 @@
     abstract val classes: ConfigurableFileCollection
 
     @get:Input
-    var packageBuildConfig: Boolean = false
-        private set
-
-    @get:Input
     abstract val packageRClass: Property<Boolean>
 
     @get:Input
@@ -87,7 +83,6 @@
                     toIgnore = toIgnoreRegExps.get(),
                     output = output.get().asFile,
                     input = classes.files,
-                    packageBuildConfig = packageBuildConfig,
                     packageRClass = packageRClass.get(),
                     jarCreatorType = jarCreatorType
                 )
@@ -163,7 +158,6 @@
             task.toIgnoreRegExps.set(
                 variantScope.globalScope.project.provider(toIgnoreRegExps::get)
             )
-            task.packageBuildConfig = variantScope.globalScope.extension.packageBuildConfig
             task.jarCreatorType = variantScope.jarCreatorType
         }
     }
@@ -176,7 +170,6 @@
         val toIgnore: List<String>,
         val output: File,
         val input: Set<File>,
-        val packageBuildConfig: Boolean,
         val packageRClass: Boolean,
         val jarCreatorType: JarCreatorType
     ) :
@@ -189,7 +182,6 @@
         val ignorePatterns =
             (LibraryAarJarsTask.getDefaultExcludes(
                 packagePath = params.packageName,
-                packageBuildConfig = params.packageBuildConfig,
                 packageR = params.packageRClass
             ) + params.toIgnore)
                 .map { Pattern.compile(it) }
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LibraryAarJarsTask.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LibraryAarJarsTask.kt
index 0061223..1b90803 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LibraryAarJarsTask.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/tasks/LibraryAarJarsTask.kt
@@ -76,10 +76,6 @@
     @get:PathSensitive(PathSensitivity.NONE)
     abstract val typedefRecipe: RegularFileProperty
 
-    @get:Input
-    abstract var packageBuildConfig: Boolean
-        protected set
-
     @get:Classpath
     abstract var mainScopeClassFiles: FileCollection
         protected set
@@ -144,7 +140,7 @@
 
     private fun computeExcludeList(): List<Pattern> {
         val excludes = getDefaultExcludes(
-            packageName.get().replace(".", "/"), packageBuildConfig)
+            packageName.get().replace(".", "/"))
 
         excludes.addAll(excludeList.get())
 
@@ -271,7 +267,7 @@
 
 
         fun getDefaultExcludes(
-            packagePath: String, packageBuildConfig: Boolean, packageR: Boolean = false
+            packagePath: String, packageR: Boolean = false
         ): MutableList<String> {
             val excludes = ArrayList<String>(5)
             if (!packageR) {
@@ -281,16 +277,12 @@
             }
             excludes.add("$packagePath/Manifest.class$")
             excludes.add("$packagePath/Manifest\\$(.*).class$")
-            if (!packageBuildConfig) {
-                excludes.add("$packagePath/BuildConfig.class$")
-            }
             return excludes
         }
     }
 
     class CreationAction(
         variantScope: VariantScope,
-        private val packageBuildConfig: Boolean,
         private val excludeListProvider: Supplier<List<String>> =  Supplier { listOf<String>() }
     ) : VariantTaskCreationAction<LibraryAarJarsTask>(variantScope) {
         override val type = LibraryAarJarsTask::class.java
@@ -340,8 +332,6 @@
             )
             task.packageName.disallowChanges()
 
-            task.packageBuildConfig = packageBuildConfig
-
             task.jarCreatorType = variantScope.jarCreatorType
 
             task.isDebugBuild = variantScope.variantConfiguration.buildType.isDebuggable
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/ApplicationVariantFactory.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/ApplicationVariantFactory.java
index fae6b3a..58eea55 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/ApplicationVariantFactory.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/ApplicationVariantFactory.java
@@ -264,6 +264,7 @@
 
     @Override
     public void validateModel(@NonNull VariantModel model) {
+        super.validateModel(model);
 
         validateVersionCodes(model);
 
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/BaseVariantFactory.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/BaseVariantFactory.java
index 0731213..2f22dca 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/BaseVariantFactory.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/BaseVariantFactory.java
@@ -19,7 +19,11 @@
 import static com.android.build.gradle.tasks.factory.AbstractCompilesUtil.ANDROID_APT_PLUGIN_NAME;
 
 import com.android.annotations.NonNull;
+import com.android.build.gradle.internal.BuildTypeData;
+import com.android.build.gradle.internal.ProductFlavorData;
+import com.android.build.gradle.internal.VariantModel;
 import com.android.build.gradle.internal.scope.GlobalScope;
+import com.android.builder.errors.EvalIssueReporter;
 import com.android.builder.errors.EvalIssueReporter.Type;
 import org.gradle.api.Project;
 
@@ -45,4 +49,37 @@
                             "android-apt");
         }
     }
+
+    @Override
+    public void validateModel(@NonNull VariantModel model) {
+        if (!globalScope.getBuildFeatures().getBuildConfig()) {
+            EvalIssueReporter issueReporter = globalScope.getErrorHandler();
+
+            if (!model.getDefaultConfig().getProductFlavor().getBuildConfigFields().isEmpty()) {
+                issueReporter.reportError(
+                        Type.GENERIC,
+                        "defaultConfig contains custom BuildConfig fields, but the feature is disabled.");
+            }
+
+            for (BuildTypeData buildType : model.getBuildTypes().values()) {
+                if (!buildType.getBuildType().getBuildConfigFields().isEmpty()) {
+                    issueReporter.reportError(
+                            Type.GENERIC,
+                            String.format(
+                                    "Build Type '%s' contains custom BuildConfig fields, but the feature is disabled.",
+                                    buildType.getBuildType().getName()));
+                }
+            }
+
+            for (ProductFlavorData productFlavor : model.getProductFlavors().values()) {
+                if (!productFlavor.getProductFlavor().getBuildConfigFields().isEmpty()) {
+                    issueReporter.reportError(
+                            Type.GENERIC,
+                            String.format(
+                                    "Product Flavor '%s' contains custom BuildConfig fields, but the feature is disabled.",
+                                    productFlavor.getProductFlavor().getName()));
+                }
+            }
+        }
+    }
 }
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/LibraryVariantFactory.java b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/LibraryVariantFactory.java
index 1b2fb2a..eb24213 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/LibraryVariantFactory.java
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/variant/LibraryVariantFactory.java
@@ -82,6 +82,8 @@
      */
     @Override
     public void validateModel(@NonNull VariantModel model) {
+        super.validateModel(model);
+
         EvalIssueReporter issueReporter = globalScope.getErrorHandler();
 
         if (model.getDefaultConfig().getProductFlavor().getApplicationId() != null) {
diff --git a/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt b/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt
index 12076bc..3455e81 100644
--- a/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt
+++ b/build-system/gradle-core/src/main/java/com/android/build/gradle/options/BooleanOption.kt
@@ -56,6 +56,11 @@
     ENABLE_STUDIO_VERSION_CHECK("android.injected.studio.version.check", true, Option.Status.STABLE),
 
     // ---------------
+    // FEATURE Default Values
+    // This is a PUBLIC API.
+    BUILD_FEATURE_BUILDCONFIG("android.defaults.buildfeatures.buildconfig", true, Option.Status.STABLE),
+
+    // ---------------
     // Lifecycle flags: Experimental stage, not yet enabled by default
     ENABLE_TEST_SHARDING("android.androidTest.shardBetweenDevices"),
     VERSION_CHECK_OVERRIDE_PROPERTY("android.overrideVersionCheck"),
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dsl/BuildTypeTest.java b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dsl/BuildTypeTest.java
index 38abd9f..0593ddb 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dsl/BuildTypeTest.java
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/dsl/BuildTypeTest.java
@@ -21,8 +21,13 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.build.gradle.AppExtension;
+import com.android.build.gradle.internal.api.dsl.DslScope;
 import com.android.build.gradle.internal.errors.DeprecationReporter;
+import com.android.build.gradle.internal.fixtures.FakeBuildFeatureValues;
+import com.android.build.gradle.internal.fixtures.FakeLogger;
+import com.android.build.gradle.internal.fixtures.FakeObjectFactory;
 import com.android.build.gradle.internal.plugins.AppPlugin;
+import com.android.build.gradle.internal.variant2.DslScopeImpl;
 import com.android.builder.core.BuilderConstants;
 import com.android.builder.errors.EvalIssueReporter;
 import com.android.sdklib.SdkVersionInfo;
@@ -40,12 +45,18 @@
 
     private EvalIssueReporter issueReporter;
     private DeprecationReporter deprecationReporter;
+    private DslScope dslScope =
+            new DslScopeImpl(
+                    new NoOpIssueReporter(),
+                    new NoOpDeprecationReporter(),
+                    new FakeObjectFactory(),
+                    new FakeLogger(),
+                    new FakeBuildFeatureValues());
+
 
     @Before
     public void setUp() throws Exception {
         project = ProjectBuilder.builder().build();
-        issueReporter = new NoOpIssueReporter();
-        deprecationReporter = new NoOpDeprecationReporter();
     }
 
     @Test
@@ -74,14 +85,9 @@
     public void testInitWith() {
         CopyOfTester.assertAllGettersCalled(
                 BuildType.class,
-                new BuildType("original", project, issueReporter, deprecationReporter),
+                new BuildType("original", project, dslScope),
                 original -> {
-                    BuildType copy =
-                            new BuildType(
-                                    original.getName(),
-                                    project,
-                                    issueReporter,
-                                    deprecationReporter);
+                    BuildType copy = new BuildType(original.getName(), project, dslScope);
                     copy.initWith(original);
 
                     // Manually call getters that don't need to be copied.
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeBuildFeatureValues.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeBuildFeatureValues.kt
new file mode 100644
index 0000000..7954bdc
--- /dev/null
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeBuildFeatureValues.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.build.gradle.internal.fixtures
+
+import com.android.build.gradle.internal.scope.BuildFeatureValues
+
+class FakeBuildFeatureValues(
+    override val jetpackCompose: Boolean = false,
+    override val buildConfig: Boolean = true) : BuildFeatureValues {
+}
\ No newline at end of file
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeObjectFactory.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeObjectFactory.kt
index 6384a15..e34e91c 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeObjectFactory.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeObjectFactory.kt
@@ -86,7 +86,7 @@
     }
 
     override fun <T : Any?> property(p0: Class<T>?): Property<T> {
-        TODO("not implemented")
+        return FakeProperty<T>()
     }
 
     override fun <T : Named?> named(p0: Class<T>?, p1: String?): T {
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeProperty.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeProperty.kt
new file mode 100644
index 0000000..feeb1d3
--- /dev/null
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/fixtures/FakeProperty.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.build.gradle.internal.fixtures
+
+import org.gradle.api.Transformer
+import org.gradle.api.provider.Property
+import org.gradle.api.provider.Provider
+
+class FakeProperty<T> : Property<T> {
+
+    private var value: T? = null
+    private var valueProvider: Provider<out T>? = null
+    private var convention: T? = null
+
+    override fun getOrElse(defaultValue: T): T {
+        return value ?: valueProvider?.get() ?: convention ?: defaultValue
+    }
+
+    override fun disallowChanges() {
+    }
+
+    override fun value(p0: T?): Property<T> {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+
+    override fun value(p0: Provider<out T>): Property<T> {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+
+    override fun getOrNull(): T? {
+        return value ?: valueProvider?.get() ?: convention
+    }
+
+    override fun set(value: T?) {
+        this.value = value
+        this.valueProvider = null
+    }
+
+    override fun set(provider: Provider<out T>) {
+        this.value = null
+        this.valueProvider = provider
+    }
+
+    override fun isPresent(): Boolean {
+        return value != null || valueProvider != null
+    }
+
+    override fun convention(value: T): Property<T> {
+        convention = value
+        return this
+    }
+
+    override fun convention(p0: Provider<out T>): Property<T> {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+
+    override fun <S : Any?> map(p0: Transformer<out S, in T>): Provider<S> {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+
+    override fun finalizeValue() {
+    }
+
+    override fun get(): T {
+        return value ?: valueProvider?.get() ?: convention ?: throw RuntimeException("no value")
+    }
+
+    override fun <S : Any?> flatMap(p0: Transformer<out Provider<out S>, in T>): Provider<S> {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+
+    override fun orElse(p0: T): Provider<T> {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+
+    override fun orElse(p0: Provider<out T>): Provider<T> {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
+}
\ No newline at end of file
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/BundleLibraryClassesRunnableTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/BundleLibraryClassesRunnableTest.kt
index 6083ba0..2b742a4 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/BundleLibraryClassesRunnableTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/internal/tasks/BundleLibraryClassesRunnableTest.kt
@@ -63,7 +63,6 @@
                 toIgnore = listOf(),
                 output = output,
                 input = input,
-                packageBuildConfig = false,
                 packageRClass = false,
                 jarCreatorType = JarCreatorType.JAR_FLINGER
             )
@@ -84,7 +83,6 @@
                 dir.resolve("test").mkdirs()
                 dir.resolve("test/R.class").createNewFile()
                 dir.resolve("test/R\$string.class").createNewFile()
-                dir.resolve("test/BuildConfig.class").createNewFile()
                 dir.resolve("test/Manifest.class").createNewFile()
                 dir.resolve("test/Manifest\$nested.class").createNewFile()
             }
@@ -95,7 +93,6 @@
                 toIgnore = listOf(),
                 output = output,
                 input = input,
-                packageBuildConfig = false,
                 packageRClass = false,
                 jarCreatorType = JarCreatorType.JAR_FLINGER
             )
@@ -103,7 +100,6 @@
         assertThatZip(output).contains("A.class")
         assertThatZip(output).doesNotContain("test/R.class")
         assertThatZip(output).doesNotContain("test/R\$string.class")
-        assertThatZip(output).doesNotContain("test/BuildConfig.class")
         assertThatZip(output).doesNotContain("test/Manifest.class")
         assertThatZip(output).doesNotContain("test/Manifest\$nested.class")
     }
@@ -117,7 +113,6 @@
                 dir.resolve("test").mkdirs()
                 dir.resolve("test/R.class").createNewFile()
                 dir.resolve("test/R\$string.class").createNewFile()
-                dir.resolve("test/BuildConfig.class").createNewFile()
                 dir.resolve("test/Manifest.class").createNewFile()
                 dir.resolve("test/Manifest\$nested.class").createNewFile()
             }
@@ -128,7 +123,6 @@
                 toIgnore = listOf(),
                 output = output,
                 input = input,
-                packageBuildConfig = false,
                 packageRClass = true,
                 jarCreatorType = JarCreatorType.JAR_FLINGER
             )
@@ -136,7 +130,6 @@
         assertThatZip(output).contains("A.class")
         assertThatZip(output).contains("test/R.class")
         assertThatZip(output).contains("test/R\$string.class")
-        assertThatZip(output).doesNotContain("test/BuildConfig.class")
         assertThatZip(output).doesNotContain("test/Manifest.class")
         assertThatZip(output).doesNotContain("test/Manifest\$nested.class")
     }
@@ -165,7 +158,6 @@
                 toIgnore = listOf(),
                 output = output,
                 input = setOf(inputJar),
-                packageBuildConfig = false,
                 packageRClass = false,
                 jarCreatorType = JarCreatorType.JAR_FLINGER
             )
@@ -197,7 +189,6 @@
                 toIgnore = listOf(".*A\\.class$"),
                 output = output,
                 input = setOf(inputJar),
-                packageBuildConfig = false,
                 packageRClass = false,
                 jarCreatorType = JarCreatorType.JAR_FLINGER
             )
diff --git a/build-system/gradle-core/src/test/java/com/android/build/gradle/tasks/BuildArtifactReportTaskTest.kt b/build-system/gradle-core/src/test/java/com/android/build/gradle/tasks/BuildArtifactReportTaskTest.kt
index f89cb53..9ac3586 100644
--- a/build-system/gradle-core/src/test/java/com/android/build/gradle/tasks/BuildArtifactReportTaskTest.kt
+++ b/build-system/gradle-core/src/test/java/com/android/build/gradle/tasks/BuildArtifactReportTaskTest.kt
@@ -16,13 +16,9 @@
 
 package com.android.build.gradle.tasks
 
-import com.android.build.gradle.internal.fixtures.FakeDeprecationReporter
 import com.android.build.gradle.internal.scope.BuildArtifactsHolder
-import com.android.build.gradle.internal.fixtures.FakeObjectFactory
 import com.android.build.gradle.internal.scope.InternalArtifactType
 import com.android.build.gradle.internal.scope.VariantBuildArtifactsHolder
-import com.android.build.gradle.internal.variant2.DslScopeImpl
-import com.android.builder.errors.FakeEvalIssueReporter
 import com.google.common.truth.Truth.assertThat
 import org.gradle.api.Project
 import org.gradle.testfixtures.ProjectBuilder
diff --git a/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt b/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt
index 1f15755..b32f393 100644
--- a/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt
+++ b/build-system/gradle-core/src/test/resources/com/android/build/gradle/pseudo-api.txt
@@ -4,7 +4,7 @@
 below are backwards compatible.
 -------------------------------------------------------------------------
 Sha256 of below classes:
-4da9c89662bd3d687a5af99490f965818263aa07141141372536892999654b2d
+a1f15cb73bfa1dc50c02533d101bb49346416fc22006b90aec1a31b92a1680bd
 -------------------------------------------------------------------------
 com.android.build.gradle.AndroidConfig
 com.android.build.gradle.AndroidConfig.getAaptOptions: com.android.build.gradle.internal.dsl.AaptOptions ()
@@ -30,7 +30,6 @@
 com.android.build.gradle.AndroidConfig.getLibraryRequests: java.util.Collection<com.android.builder.core.LibraryRequest> ()
 com.android.build.gradle.AndroidConfig.getLintOptions: com.android.build.gradle.internal.dsl.LintOptions ()
 com.android.build.gradle.AndroidConfig.getNdkVersion: java.lang.String ()
-com.android.build.gradle.AndroidConfig.getPackageBuildConfig: java.lang.Boolean ()
 com.android.build.gradle.AndroidConfig.getPackagingOptions: com.android.build.gradle.internal.dsl.PackagingOptions ()
 com.android.build.gradle.AndroidConfig.getProductFlavors: java.util.Collection<? extends com.android.build.gradle.internal.dsl.CoreProductFlavor> ()
 com.android.build.gradle.AndroidConfig.getResourcePrefix: java.lang.String ()
@@ -107,7 +106,6 @@
 com.android.build.gradle.BaseExtension.getLintOptions: com.android.build.gradle.internal.dsl.LintOptions ()
 com.android.build.gradle.BaseExtension.getNdkDirectory: java.io.File ()
 com.android.build.gradle.BaseExtension.getNdkVersion: java.lang.String ()
-com.android.build.gradle.BaseExtension.getPackageBuildConfig: java.lang.Boolean ()
 com.android.build.gradle.BaseExtension.getPackagingOptions: com.android.build.gradle.internal.dsl.PackagingOptions ()
 com.android.build.gradle.BaseExtension.getProductFlavors: java.util.Collection ()
 com.android.build.gradle.BaseExtension.getProductFlavors: org.gradle.api.NamedDomainObjectContainer<com.android.build.gradle.internal.dsl.ProductFlavor> ()
@@ -177,10 +175,7 @@
 com.android.build.gradle.LibraryExtension.aidlPackageWhiteList: void (java.lang.String[])
 com.android.build.gradle.LibraryExtension.getAidlPackageWhiteList: java.util.Collection<java.lang.String> ()
 com.android.build.gradle.LibraryExtension.getLibraryVariants: org.gradle.api.internal.DefaultDomainObjectSet<com.android.build.gradle.api.LibraryVariant> ()
-com.android.build.gradle.LibraryExtension.getPackageBuildConfig: java.lang.Boolean ()
-com.android.build.gradle.LibraryExtension.packageBuildConfig: void (boolean)
 com.android.build.gradle.LibraryExtension.setAidlPackageWhiteList: void (java.util.Collection<java.lang.String>)
-com.android.build.gradle.LibraryExtension.setPackageBuildConfig: void (boolean)
 com.android.build.gradle.LibraryPlugin extends com.android.build.gradle.BasePlugin
 com.android.build.gradle.LibraryPlugin.<init>: com.android.build.gradle.LibraryPlugin ()
 com.android.build.gradle.LibraryPlugin.apply: void (java.lang.Object)
diff --git a/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AppAndLibNoBuildConfigTest.kt b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AppAndLibNoBuildConfigTest.kt
new file mode 100644
index 0000000..c3115f8
--- /dev/null
+++ b/build-system/integration-test/application/src/test/java/com/android/build/gradle/integration/application/AppAndLibNoBuildConfigTest.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.build.gradle.integration.application
+
+import com.android.build.gradle.integration.common.fixture.GradleTestProject
+import com.android.build.gradle.integration.common.truth.AarSubject
+import com.android.build.gradle.integration.common.truth.ApkSubject
+import com.android.build.gradle.integration.common.truth.ScannerSubject
+import com.android.build.gradle.options.BooleanOption
+import com.google.common.truth.Truth
+import org.junit.Before
+import org.junit.BeforeClass
+import org.junit.ClassRule
+import org.junit.Rule
+import org.junit.Test
+
+class AppAndLibNoBuildConfigTest {
+    @get:Rule
+    val project: GradleTestProject = GradleTestProject.builder()
+        .fromTestProject("applibtest")
+        .withoutNdk()
+        .create()
+
+    @Before
+    fun setUp() {
+        project.gradlePropertiesFile
+            .appendText("\n${BooleanOption.BUILD_FEATURE_BUILDCONFIG.propertyName}=false\n")
+    }
+
+    @Test
+    fun `ensure buildConfig is not in the APK`() {
+        project.execute("app:assembleDebug")
+
+        val debugApk = project.getSubproject(":app").getApk(GradleTestProject.ApkType.DEBUG)
+        ApkSubject.assertThat(debugApk)
+            .doesNotContainClass("Lcom/android/tests/testprojecttest/lib/BuildConfig;")
+        ApkSubject.assertThat(debugApk)
+            .doesNotContainClass("Lcom/android/tests/testprojecttest/app/BuildConfig;")
+    }
+
+    @Test
+    fun `ensure buildConfig is not in the AAR`() {
+        project.execute("lib:assembleDebug")
+
+        val debugAar = project.getSubproject(":lib").getAar("debug")
+        AarSubject.assertThat(debugAar)
+            .doesNotContainClass("Lcom/android/tests/testprojecttest/lib/BuildConfig;")
+    }
+
+    @Test
+    fun `ensure defaultConfig-buildConfigField fails`() {
+        project.getSubproject(":app")
+            .buildFile.appendText("\nandroid.defaultConfig.buildConfigField(\"boolean\", \"foo\", \"true\")")
+        val failure = project.executor().expectFailure().run("project")
+        failure.stderr.use {
+            ScannerSubject.assertThat(it)
+                .contains("defaultConfig contains custom BuildConfig fields, but the feature is disabled.")
+        }
+    }
+
+    @Test
+    fun `ensure buildtypes-buildConfigField fails`() {
+        project.getSubproject(":app")
+            .buildFile.appendText("\nandroid.buildTypes.debug.buildConfigField(\"boolean\", \"foo\", \"true\")")
+        val failure = project.executor().expectFailure().run("project")
+        failure.stderr.use {
+            ScannerSubject.assertThat(it)
+                .contains("Build Type 'debug' contains custom BuildConfig fields, but the feature is disabled.")
+        }
+    }
+}
\ No newline at end of file
diff --git a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/truth/AbstractDexAndroidSubject.java b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/truth/AbstractDexAndroidSubject.java
index 49de0e4..b59efd7 100644
--- a/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/truth/AbstractDexAndroidSubject.java
+++ b/build-system/integration-test/framework/src/main/java/com/android/build/gradle/integration/common/truth/AbstractDexAndroidSubject.java
@@ -97,6 +97,7 @@
     private DexBackedClassDef getMainClass(@NonNull String className) throws IOException {
         Optional<Dex> classesDex = actual().getMainDexFile();
         if (!classesDex.isPresent()) {
+            fail("has main dex file");
             return null;
         }
         return classesDex.get().getClasses().get(className);
diff --git a/build-system/integration-test/test-projects/applibtest/app/src/main/java/RandomClass.java b/build-system/integration-test/test-projects/applibtest/app/src/main/java/RandomClass.java
new file mode 100644
index 0000000..595cfbf
--- /dev/null
+++ b/build-system/integration-test/test-projects/applibtest/app/src/main/java/RandomClass.java
@@ -0,0 +1,3 @@
+public class RandomClass {
+    public RandomClass() {}
+}