Add configuration for android data binding v2.

RELNOTES: None
PiperOrigin-RevId: 207592136
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java b/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java
index d021892..46f3918 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AarImport.java
@@ -108,7 +108,7 @@
                   ruleContext,
                   dataContext,
                   manifest,
-                  DataBinding.contextFrom(ruleContext),
+                  DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()),
                   neverlink);
       MergedAndroidAssets mergedAssets =
           AndroidAssets.forAarImport(assets)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
index dc4b78d..90c9c6f 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidBinary.java
@@ -225,7 +225,7 @@
                           .getPrerequisite("feature_after", Mode.TARGET, ApkInfo.PROVIDER)
                           .getApk()
                       : null,
-                  DataBinding.contextFrom(ruleContext))
+                  DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()))
               .generateRClass(dataContext, aaptVersion);
     } else {
       applicationManifest =
@@ -246,7 +246,7 @@
           applicationManifest.packBinaryWithDataAndResources(
               ruleContext,
               dataContext,
-              DataBinding.contextFrom(ruleContext),
+              DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()),
               ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK),
               resourceDeps,
               ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT),
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
index 00134a7..752b8cf 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidConfiguration.java
@@ -52,6 +52,7 @@
 @Immutable
 public class AndroidConfiguration extends BuildConfiguration.Fragment
     implements AndroidConfigurationApi {
+
   /**
    * Converter for {@link
    * com.google.devtools.build.lib.rules.android.AndroidConfiguration.ConfigurationDistinguisher}
@@ -729,6 +730,19 @@
     public boolean compressJavaResources;
 
     @Option(
+        name = "experimental_android_databinding_v2",
+        defaultValue = "false",
+        documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
+        effectTags = {
+          OptionEffectTag.AFFECTS_OUTPUTS,
+          OptionEffectTag.LOADING_AND_ANALYSIS,
+          OptionEffectTag.LOSES_INCREMENTAL_STATE,
+        },
+        metadataTags = OptionMetadataTag.EXPERIMENTAL,
+        help = "Use android databinding v2")
+    public boolean dataBindingV2;
+
+    @Option(
       name = "experimental_android_library_exports_manifest_default",
       defaultValue = "false",
       documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
@@ -922,6 +936,7 @@
   private final boolean decoupleDataProcessing;
   private final boolean checkForMigrationTag;
   private final boolean oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest;
+  private final boolean dataBindingV2;
 
   AndroidConfiguration(Options options) throws InvalidConfigurationException {
     this.sdk = options.sdk;
@@ -963,6 +978,7 @@
     this.checkForMigrationTag = options.checkForMigrationTag;
     this.oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest =
         options.oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest;
+    this.dataBindingV2 = options.dataBindingV2;
 
     if (incrementalDexingShardsAfterProguard < 0) {
       throw new InvalidConfigurationException(
@@ -1015,7 +1031,8 @@
       AndroidRobolectricTestDeprecationLevel robolectricTestDeprecationLevel,
       boolean decoupleDataProcessing,
       boolean checkForMigrationTag,
-      boolean oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest) {
+      boolean oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest,
+      boolean dataBindingV2) {
     this.sdk = sdk;
     this.cpu = cpu;
     this.useIncrementalNativeLibs = useIncrementalNativeLibs;
@@ -1052,6 +1069,7 @@
     this.checkForMigrationTag = checkForMigrationTag;
     this.oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest =
         oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest;
+    this.dataBindingV2 = dataBindingV2;
   }
 
   public String getCpu() {
@@ -1211,6 +1229,10 @@
     return oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest;
   }
 
+  public boolean useDataBindingV2() {
+    return dataBindingV2;
+  }
+
   @Override
   public String getOutputDirectoryName() {
     return configurationDistinguisher.suffix;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
index 8ed119b..963ac63 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLibrary.java
@@ -169,7 +169,7 @@
                     ruleContext,
                     dataContext,
                     manifest,
-                    DataBinding.contextFrom(ruleContext),
+                    DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()),
                     isNeverLink);
 
         MergedAndroidAssets assets =
@@ -196,7 +196,7 @@
                 ruleContext.getImplicitOutputArtifact(
                     AndroidRuleClasses.ANDROID_PROCESSED_MANIFEST),
                 ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_ZIP),
-                DataBinding.contextFrom(ruleContext));
+                DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()));
       }
       if (ruleContext.hasErrors()) {
         return null;
@@ -206,7 +206,7 @@
       resourceApk =
           ResourceApk.processFromTransitiveLibraryData(
               dataContext,
-              DataBinding.contextFrom(ruleContext),
+              DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()),
               resourceDeps,
               assetDeps,
               StampedAndroidManifest.createEmpty(ruleContext, /* exported = */ false));
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java
index 55fe52f..6e6743c 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidLocalTestBase.java
@@ -101,7 +101,7 @@
           buildResourceApk(
               dataContext,
               androidSemantics,
-              DataBinding.contextFrom(ruleContext),
+              DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()),
               AndroidManifest.fromAttributes(ruleContext, dataContext),
               AndroidResources.from(ruleContext, "resource_files"),
               AndroidAssets.from(ruleContext),
@@ -122,7 +122,7 @@
           applicationManifest.packBinaryWithDataAndResources(
               ruleContext,
               dataContext,
-              DataBinding.contextFrom(ruleContext),
+              DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()),
               ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_RESOURCES_APK),
               resourceDependencies,
               ruleContext.getImplicitOutputArtifact(AndroidRuleClasses.ANDROID_R_TXT),
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
index 8d48497..02f9808 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidSkylarkData.java
@@ -175,7 +175,10 @@
                   ctx,
                   manifest.asStampedManifest(),
                   ResourceDependencies.fromProviders(deps, neverlink),
-                  DataBinding.contextFrom(enableDataBinding, ctx.getActionConstructionContext()),
+                  DataBinding.contextFrom(
+                      enableDataBinding,
+                      ctx.getActionConstructionContext(),
+                      ctx.getAndroidConfig()),
                   aaptVersion);
 
       JavaInfo javaInfo = getJavaInfoForRClassJar(validated.getClassJar());
@@ -581,7 +584,10 @@
                   crunchPng,
                   /* featureOf = */ null,
                   /* featureAfter = */ null,
-                  DataBinding.contextFrom(dataBindingEnabled, ctx.getActionConstructionContext()))
+                  DataBinding.contextFrom(
+                      dataBindingEnabled,
+                      ctx.getActionConstructionContext(),
+                      ctx.getAndroidConfig()))
               .generateRClass(ctx, settings.aaptVersion);
 
       return AndroidBinaryDataInfo.of(
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
index 94e99ac..b0b0810 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ApplicationManifest.java
@@ -420,7 +420,10 @@
           .setSourceJarOut(resourceContainer.getJavaSourceJar());
     }
     ResourceContainer processed =
-        builder.build(dataContext, resourceContainer, DataBinding.contextFrom(ruleContext));
+        builder.build(
+            dataContext,
+            resourceContainer,
+            DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()));
 
     ResourceContainer finalContainer =
         new RClassGeneratorActionBuilder()
@@ -496,7 +499,10 @@
             .setStaticLibraryOut(merged.getStaticLibrary())
             .build(dataContext, merged);
 
-    return ResourceApk.of(processed, resourceDeps, DataBinding.contextFrom(ruleContext));
+    return ResourceApk.of(
+        processed,
+        resourceDeps,
+        DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()));
   }
 
   /* Creates an incremental apk from assets and data. */
@@ -550,12 +556,19 @@
                     .getFragment(AndroidConfiguration.class)
                     .throwOnResourceConflict())
             .setPackageUnderTest(null)
-            .build(dataContext, resourceContainer, DataBinding.contextFrom(ruleContext));
+            .build(
+                dataContext,
+                resourceContainer,
+                DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()));
 
     // Intentionally skip building an R class JAR - incremental binaries handle this separately.
 
     return ResourceApk.of(
-        processed, resourceDeps, proguardCfg, null, DataBinding.contextFrom(ruleContext));
+        processed,
+        resourceDeps,
+        proguardCfg,
+        null,
+        DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()));
   }
 
   /** Packages up the manifest with resource and assets from the rule and dependent resources. */
@@ -636,7 +649,10 @@
             .setRTxtOut(resourceContainer.getRTxt())
             .setSymbols(resourceContainer.getSymbols())
             .setSourceJarOut(resourceContainer.getJavaSourceJar())
-            .build(dataContext, resourceContainer, DataBinding.contextFrom(ruleContext));
+            .build(
+                dataContext,
+                resourceContainer,
+                DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()));
 
     ResourceContainer finalContainer =
         new RClassGeneratorActionBuilder()
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java b/src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java
index 9564643..a5c4c33 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/DataBinding.java
@@ -148,11 +148,11 @@
     }
   }
 
-  private static final class EnabledDataBindingContext implements DataBindingContext {
+  private static final class EnabledDataBindingV1Context implements DataBindingContext {
 
     private final ActionConstructionContext actionConstructionContext;
 
-    private EnabledDataBindingContext(ActionConstructionContext actionConstructionContext) {
+    private EnabledDataBindingV1Context(ActionConstructionContext actionConstructionContext) {
       this.actionConstructionContext = actionConstructionContext;
     }
 
@@ -269,7 +269,7 @@
       if (o == null || getClass() != o.getClass()) {
         return false;
       }
-      EnabledDataBindingContext that = (EnabledDataBindingContext) o;
+      EnabledDataBindingV1Context that = (EnabledDataBindingV1Context) o;
       return Objects.equals(actionConstructionContext, that.actionConstructionContext);
     }
 
@@ -284,28 +284,52 @@
     }
   }
 
+  private static class EnabledDataBindingV2Context implements DataBindingContext {
+
+    private final ActionConstructionContext actionContext;
+
+    private EnabledDataBindingV2Context(ActionConstructionContext actionContext) {
+      this.actionContext = actionContext;
+      throw new UnsupportedOperationException("V2 not implemented yet.");
+    }
+    // TODO(b/112038432): Enable databinding v2.
+  }
+
   private static final DataBindingContext DISABLED_CONTEXT = new DataBindingContext() {};
 
   /** Supplies a databinding context from a rulecontext. */
-  public static DataBindingContext contextFrom(RuleContext ruleContext) {
+  public static DataBindingContext contextFrom(
+      RuleContext ruleContext, AndroidConfiguration androidConfig) {
     if (isEnabled(ruleContext)) {
-      return asEnabledDataBindingContextFrom(ruleContext);
+      if (androidConfig.useDataBindingV2()) {
+        return asEnabledDataBindingV2ContextFrom(ruleContext);
+      }
+      return asEnabledDataBindingV1ContextFrom(ruleContext);
     }
     return asDisabledDataBindingContext();
   }
 
   /** Supplies a databinding context from an action context. */
-  public static DataBindingContext contextFrom(boolean enabled, ActionConstructionContext context) {
+  public static DataBindingContext contextFrom(
+      boolean enabled, ActionConstructionContext context, AndroidConfiguration androidConfig) {
     if (enabled) {
-      return asEnabledDataBindingContextFrom(context);
+      if (androidConfig.useDataBindingV2()) {
+        return asEnabledDataBindingV2ContextFrom(context);
+      }
+      return asEnabledDataBindingV1ContextFrom(context);
     }
     return asDisabledDataBindingContext();
   }
 
   /** Supplies an enabled DataBindingContext from the action context. */
-  public static DataBindingContext asEnabledDataBindingContextFrom(
+  private static DataBindingContext asEnabledDataBindingV1ContextFrom(
       ActionConstructionContext actionContext) {
-    return new EnabledDataBindingContext(actionContext);
+    return new EnabledDataBindingV1Context(actionContext);
+  }
+
+  private static DataBindingContext asEnabledDataBindingV2ContextFrom(
+      ActionConstructionContext actionContext) {
+    return new EnabledDataBindingV2Context(actionContext);
   }
 
   /** Supplies a disabled (no-op) DataBindingContext. */
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java b/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java
index d0bd385..90a55e2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ProcessedAndroidData.java
@@ -124,7 +124,7 @@
 
     return buildActionForBinary(
         dataContext,
-        DataBinding.contextFrom(ruleContext),
+        DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()),
         ruleContext,
         builder,
         manifest,
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java
index d1f9db8..d60f365 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidResourcesTest.java
@@ -145,13 +145,14 @@
       ImmutableList<Artifact> unfilteredResources, ImmutableList<Artifact> filteredResources)
       throws Exception {
     RuleContext ruleContext = getRuleContext();
+    final AndroidDataContext dataContext = AndroidDataContext.forNative(ruleContext);
     ValidatedAndroidResources unfiltered =
         new AndroidResources(unfilteredResources, getResourceRoots(unfilteredResources))
             .process(
                 ruleContext,
-                AndroidDataContext.forNative(ruleContext),
+                dataContext,
                 getManifest(),
-                DataBinding.contextFrom(ruleContext),
+                DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()),
                 /* neverlink = */ false);
     Optional<? extends AndroidResources> maybeFiltered =
         assertFilter(unfiltered, filteredResources, /* isDependency = */ true);
@@ -227,7 +228,11 @@
 
     RuleContext ruleContext = getRuleContext();
     ParsedAndroidResources parsed =
-        assertParse(ruleContext, DataBinding.asEnabledDataBindingContextFrom(ruleContext));
+        assertParse(
+            ruleContext,
+            DataBinding.contextFrom(
+                ruleContext,
+                ruleContext.getConfiguration().getFragment(AndroidConfiguration.class)));
 
     // Since we are not using aapt2, there should be no compiled symbols
     assertThat(parsed.getCompiledSymbols()).isNull();
@@ -498,7 +503,7 @@
                 false,
                 null,
                 null,
-                DataBinding.contextFrom(ruleContext))
+                DataBinding.contextFrom(ruleContext, dataContext.getAndroidConfig()))
             .generateRClass(dataContext, AndroidAaptVersion.AUTO);
 
     assertThat(resourceApk.getResourceProguardConfig()).isNotNull();
@@ -510,7 +515,10 @@
    * for further validation.
    */
   private ParsedAndroidResources assertParse(RuleContext ruleContext) throws Exception {
-    return assertParse(ruleContext, DataBinding.contextFrom(ruleContext));
+    return assertParse(
+        ruleContext,
+        DataBinding.contextFrom(
+            ruleContext, ruleContext.getConfiguration().getFragment(AndroidConfiguration.class)));
   }
 
   private ParsedAndroidResources assertParse(