Add support for databinding-generated sources to depend on AndroidX instead of the support libraries.

Note that the Android databinding libraries already support AndroidX support. This CL is primarily introducing a new AndroidX databinding flag and propagating it to the necessary places. This required introducing new flags for some of the actions that correspond to kicking off various parts of the databinding process.

The new flag being introduced is: android_databinding_use_androidx.

The new tests are primarily ensuring each action tied to databinding has the new androidx parameter passed to it. Unfortunately, this only relies on rule analysis and doesn't actually verify that the actions themselves behave correctly with the flag enabled. Similarly, the databinding mapper implementation file switching logic changes can't be tested without executing the actions. Please advise on how to test this if it's valuable.

RELNOTES: Add support for using AndroidX dependencies in data-binding-enabled targets.
PiperOrigin-RevId: 339381866
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java
index ad168fd..1bc7063 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidAssets.java
@@ -171,7 +171,8 @@
     return assetDir;
   }
 
-  public ParsedAndroidAssets parse(AndroidDataContext dataContext) throws InterruptedException {
+  @VisibleForTesting
+  ParsedAndroidAssets parse(AndroidDataContext dataContext) throws InterruptedException {
     return ParsedAndroidAssets.parseFrom(dataContext, this);
   }
 
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 60f771b..4e58956 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
@@ -672,6 +672,21 @@
     public boolean dataBindingUpdatedArgs;
 
     @Option(
+        name = "android_databinding_use_androidx",
+        defaultValue = "false",
+        documentationCategory = OptionDocumentationCategory.OUTPUT_PARAMETERS,
+        effectTags = {
+          OptionEffectTag.AFFECTS_OUTPUTS,
+          OptionEffectTag.LOADING_AND_ANALYSIS,
+          OptionEffectTag.LOSES_INCREMENTAL_STATE,
+        },
+        metadataTags = OptionMetadataTag.EXPERIMENTAL,
+        help =
+            "Generate AndroidX-compatible data-binding files. "
+                + "This is only used with databinding v2.")
+    public boolean dataBindingAndroidX;
+
+    @Option(
         name = "experimental_android_library_exports_manifest_default",
         defaultValue = "false",
         documentationCategory = OptionDocumentationCategory.UNDOCUMENTED,
@@ -989,6 +1004,7 @@
   private final boolean oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest;
   private final boolean dataBindingV2;
   private final boolean dataBindingUpdatedArgs;
+  private final boolean dataBindingAndroidX;
   private final boolean persistentBusyboxTools;
   private final boolean filterRJarsFromAndroidTest;
   private final boolean removeRClassesFromInstrumentationTestJar;
@@ -1043,6 +1059,7 @@
         options.oneVersionEnforcementUseTransitiveJarsForBinaryUnderTest;
     this.dataBindingV2 = options.dataBindingV2;
     this.dataBindingUpdatedArgs = options.dataBindingUpdatedArgs;
+    this.dataBindingAndroidX = options.dataBindingAndroidX;
     this.persistentBusyboxTools = options.persistentBusyboxTools;
     this.filterRJarsFromAndroidTest = options.filterRJarsFromAndroidTest;
     this.removeRClassesFromInstrumentationTestJar =
@@ -1277,6 +1294,11 @@
   }
 
   @Override
+  public boolean useDataBindingAndroidX() {
+    return dataBindingAndroidX;
+  }
+
+  @Override
   public boolean persistentBusyboxTools() {
     return persistentBusyboxTools;
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingProcessorBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingProcessorBuilder.java
index 8c7f304..7fc3258 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingProcessorBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingProcessorBuilder.java
@@ -29,13 +29,15 @@
    * @param androidResources The resources to process.
    * @param appId The app id (the app's java package).
    * @param dataBindingLayoutInfoOut The output layout info file to write.
+   * @param useDataBindingAndroidX Whether generated files should use AndroidX dependencies.
    * @return The new AndroidResources that has been processed by databinding.
    */
   public static AndroidResources create(
       AndroidDataContext dataContext,
       AndroidResources androidResources,
       String appId,
-      Artifact dataBindingLayoutInfoOut) {
+      Artifact dataBindingLayoutInfoOut,
+      boolean useDataBindingAndroidX) {
 
     ImmutableList.Builder<Artifact> databindingProcessedResourcesBuilder = ImmutableList.builder();
     for (Artifact resource : androidResources.getResources()) {
@@ -89,6 +91,7 @@
 
     builder.addOutput("--dataBindingInfoOut", dataBindingLayoutInfoOut);
     builder.addFlag("--appId", appId);
+    builder.maybeAddFlag("--useDataBindingAndroidX", useDataBindingAndroidX);
 
     builder.buildAndRegister("Processing data binding", "ProcessDatabinding");
 
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataContext.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataContext.java
index bdfed20..ffe7c16 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataContext.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidDataContext.java
@@ -68,6 +68,7 @@
   private final boolean throwOnProguardApplyMapping;
   private final boolean throwOnResourceConflict;
   private final boolean useDataBindingV2;
+  private final boolean useDataBindingAndroidX;
 
   public static AndroidDataContext forNative(RuleContext ruleContext) {
     return makeContext(ruleContext);
@@ -88,7 +89,8 @@
         !hasExemption(ruleContext, "allow_proguard_apply_dictionary", true),
         !hasExemption(ruleContext, "allow_proguard_apply_mapping", true),
         !hasExemption(ruleContext, "allow_resource_conflicts", true),
-        androidConfig.useDataBindingV2());
+        androidConfig.useDataBindingV2(),
+        androidConfig.useDataBindingAndroidX());
   }
 
   private static boolean hasExemption(
@@ -109,7 +111,8 @@
       boolean throwOnProguardApplyDictionary,
       boolean throwOnProguardApplyMapping,
       boolean throwOnResourceConflict,
-      boolean useDataBindingV2) {
+      boolean useDataBindingV2,
+      boolean useDataBindingAndroidX) {
     this.persistentBusyboxToolsEnabled = persistentBusyboxToolsEnabled;
     this.ruleContext = ruleContext;
     this.busybox = busybox;
@@ -121,6 +124,7 @@
     this.throwOnProguardApplyMapping = throwOnProguardApplyMapping;
     this.throwOnResourceConflict = throwOnResourceConflict;
     this.useDataBindingV2 = useDataBindingV2;
+    this.useDataBindingAndroidX = useDataBindingAndroidX;
   }
 
   public Label getLabel() {
@@ -223,6 +227,10 @@
     return useDataBindingV2;
   }
 
+  public boolean useDataBindingAndroidX() {
+    return useDataBindingAndroidX;
+  }
+
   public boolean annotateRFieldsFromTransitiveDeps() {
     return ruleContext.getFeatures().contains(ANNOTATE_R_FIELDS_FROM_TRANSITIVE_DEPS);
   }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceParsingActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceParsingActionBuilder.java
index 8d29b68..ae69693 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceParsingActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourceParsingActionBuilder.java
@@ -100,7 +100,8 @@
           BusyBoxActionBuilder.create(dataContext, "COMPILE_LIBRARY_RESOURCES")
               .addAapt()
               .addInput("--resources", resourceDirectories, resourceArtifacts)
-              .addOutput("--output", compiledSymbols);
+              .addOutput("--output", compiledSymbols)
+              .maybeAddFlag("--useDataBindingAndroidX", dataContext.useDataBindingAndroidX());
 
       if (dataBindingInfoZip != null) {
         compiledBuilder
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
index 981de47..1fccf06 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/AndroidResourcesProcessorBuilder.java
@@ -206,7 +206,11 @@
         dataContext, primaryResources, processedManifest.getPackage());
 
     createAapt2ApkAction(
-        dataContext, databindingProcessedResources, primaryAssets, primaryManifest);
+        dataContext,
+        databindingProcessedResources,
+        primaryAssets,
+        primaryManifest,
+        dataBindingContext.usesAndroidX());
 
     // Wrap the parsed resources
     ParsedAndroidResources parsedResources =
@@ -274,7 +278,8 @@
       AndroidDataContext dataContext,
       AndroidResources primaryResources,
       AndroidAssets primaryAssets,
-      StampedAndroidManifest primaryManifest) {
+      StampedAndroidManifest primaryManifest,
+      boolean useDataBindingAndroidX) {
     BusyBoxActionBuilder builder =
         BusyBoxActionBuilder.create(dataContext, "AAPT2_PACKAGE").addAapt();
 
@@ -310,7 +315,13 @@
 
     builder.maybeAddFlag("--conditionalKeepRules", conditionalKeepRules);
 
-    configureCommonFlags(dataContext, primaryResources, primaryAssets, primaryManifest, builder)
+    configureCommonFlags(
+            dataContext,
+            primaryResources,
+            primaryAssets,
+            primaryManifest,
+            useDataBindingAndroidX,
+            builder)
         .buildAndRegister("Processing Android resources", "AndroidAapt2");
   }
 
@@ -319,6 +330,7 @@
       AndroidResources primaryResources,
       AndroidAssets primaryAssets,
       StampedAndroidManifest primaryManifest,
+      boolean useDataBindingAndroidX,
       BusyBoxActionBuilder builder) {
 
     return builder
@@ -352,6 +364,7 @@
         // and because its resource filtering is somewhat stricter for locales, and resource
         // processing needs access to densities to add them to the manifest.
         .maybeAddFlag("--resourceConfigs", resourceFilterFactory.getConfigurationFilterString())
+        .maybeAddFlag("--useDataBindingAndroidX", useDataBindingAndroidX)
         .maybeAddFlag("--densities", resourceFilterFactory.getDensityString())
         .maybeAddVectoredFlag("--uncompressedExtensions", uncompressedExtensions)
         .maybeAddFlag("--useAaptCruncher=no", !crunchPng)
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/BUILD b/src/main/java/com/google/devtools/build/lib/rules/android/BUILD
index 3c67766..e148294 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/BUILD
@@ -22,7 +22,8 @@
     resources = [
         "android_device_stub_template.txt",
         "android_instrumentation_test_template.txt",
-        "databinding/databinding_annotation_template.txt",
+        "databinding/databinding_annotation_template_androidx.txt",
+        "databinding/databinding_annotation_template_support_lib.txt",
         "robolectric_properties_template.txt",
         "test_suite_property_name.txt",
     ],
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
index 999a392..1d5ace1 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/ResourceShrinkerActionBuilder.java
@@ -117,6 +117,7 @@
         .addOutput("--shrunkResources", shrunkResourcesOut)
         .maybeAddOutput("--resourcesConfigOutput", resourceOptimizationConfigOut)
         .addOutput("--log", logOut)
+        .maybeAddFlag("--useDataBindingAndroidX", dataContext.useDataBindingAndroidX())
         .buildAndRegister("Shrinking resources", "ResourceShrinker");
 
     return resourceApkOut;
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBinding.java b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBinding.java
index e302ce2..f602ed2 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBinding.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBinding.java
@@ -91,7 +91,10 @@
 
     if (enabled) {
       if (androidConfig.useDataBindingV2()) {
-        return new DataBindingV2Context(context, androidConfig.useDataBindingUpdatedArgs());
+        return new DataBindingV2Context(
+            context,
+            androidConfig.useDataBindingUpdatedArgs(),
+            androidConfig.useDataBindingAndroidX());
       } else {
         return new DataBindingV1Context(context, androidConfig.useDataBindingUpdatedArgs());
       }
@@ -148,7 +151,7 @@
         binRelativeBasePath.getRelative(relativePath), ruleContext.getBinOrGenfilesDirectory());
   }
 
-  static ImmutableList<Artifact> getAnnotationFile(RuleContext ruleContext) {
+  static ImmutableList<Artifact> getAnnotationFile(RuleContext ruleContext, boolean useAndroidX) {
     // Add this rule's annotation processor input. If the rule doesn't have direct resources,
     // there's no direct data binding info, so there's strictly no need for annotation processing.
     // But it's still important to process the deps' .bin files so any Java class references get
@@ -160,7 +163,10 @@
     try {
       String contents =
           ResourceFileLoader.loadResource(
-              DataBinding.class, "databinding_annotation_template.txt");
+              DataBinding.class,
+              useAndroidX
+                  ? "databinding_annotation_template_androidx.txt"
+                  : "databinding_annotation_template_support_lib.txt");
       Artifact annotationFile = getDataBindingArtifact(ruleContext, "DataBindingInfo.java");
       ruleContext.registerAction(
           FileWriteAction.create(ruleContext, annotationFile, contents, false));
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingContext.java b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingContext.java
index c57c90e..585c013 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingContext.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingContext.java
@@ -109,4 +109,7 @@
       AndroidDataContext dataContext,
       AndroidResources resources,
       String appId);
+
+  /** Returns whether this context supports generating AndroidX dependencies. */
+  boolean usesAndroidX();
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV1Context.java b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV1Context.java
index fa36c32..bdd0b36 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV1Context.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV1Context.java
@@ -106,7 +106,7 @@
 
   @Override
   public ImmutableList<Artifact> getAnnotationSourceFiles(RuleContext ruleContext) {
-    return DataBinding.getAnnotationFile(ruleContext);
+    return DataBinding.getAnnotationFile(ruleContext, /* useAndroidX= */ false);
   }
 
   @Override
@@ -135,4 +135,10 @@
       AndroidDataContext dataContext, AndroidResources resources, String appId) {
     return resources;
   }
+
+  @Override
+  public boolean usesAndroidX() {
+    // AndroidX dependencies are only supported with databinding v2.
+    return false;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV2Context.java b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV2Context.java
index 95c025f..4575d79 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV2Context.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DataBindingV2Context.java
@@ -46,6 +46,7 @@
 
   private final ActionConstructionContext actionContext;
   private final boolean useUpdatedArgs;
+  private final boolean useAndroidX;
   /**
    * Annotation processing creates the following metadata files that describe how data binding is
    * applied. The full file paths include prefixes as implemented in {@link #getMetadataOutputs}.
@@ -54,9 +55,11 @@
 
   private final String setterStoreName;
 
-  DataBindingV2Context(ActionConstructionContext actionContext, boolean useUpdatedArgs) {
+  DataBindingV2Context(
+      ActionConstructionContext actionContext, boolean useUpdatedArgs, boolean useAndroidX) {
     this.actionContext = actionContext;
     this.useUpdatedArgs = useUpdatedArgs;
+    this.useAndroidX = useAndroidX;
     this.setterStoreName = useUpdatedArgs ? "setter_store.json" : "setter_store.bin";
     metadataOutputSuffixes = ImmutableList.of(setterStoreName, "br.bin");
   }
@@ -256,7 +259,7 @@
   public ImmutableList<Artifact> getAnnotationSourceFiles(RuleContext ruleContext) {
     ImmutableList.Builder<Artifact> srcs = ImmutableList.builder();
 
-    srcs.addAll(DataBinding.getAnnotationFile(ruleContext));
+    srcs.addAll(DataBinding.getAnnotationFile(ruleContext, useAndroidX));
     srcs.addAll(createBaseClasses(ruleContext));
 
     return srcs.build();
@@ -275,14 +278,15 @@
     FilesToRunProvider exec =
         ruleContext.getExecutablePrerequisite(DataBinding.DATABINDING_EXEC_PROCESSOR_ATTR);
 
-    CustomCommandLine.Builder commandLineBuilder = CustomCommandLine.builder()
-        .add("GEN_BASE_CLASSES")
-        .addExecPath("-layoutInfoFiles", layoutInfo)
-        .add("-package", AndroidCommon.getJavaPackage(ruleContext))
-        .addExecPath("-classInfoOut", classInfoFile)
-        .addExecPath("-sourceOut", srcOutFile)
-        .add("-zipSourceOutput", "true")
-        .add("-useAndroidX", "false");
+    CustomCommandLine.Builder commandLineBuilder =
+        CustomCommandLine.builder()
+            .add("GEN_BASE_CLASSES")
+            .addExecPath("-layoutInfoFiles", layoutInfo)
+            .add("-package", AndroidCommon.getJavaPackage(ruleContext))
+            .addExecPath("-classInfoOut", classInfoFile)
+            .addExecPath("-sourceOut", srcOutFile)
+            .add("-zipSourceOutput", "true")
+            .add("-useAndroidX", useAndroidX ? "true" : "false");
 
     List<Artifact> dependencyClassInfo = getDirectClassInfo(ruleContext);
     for (Artifact artifact : dependencyClassInfo) {
@@ -364,14 +368,20 @@
   public AndroidResources processResources(
       AndroidDataContext dataContext, AndroidResources resources, String appId) {
 
-    AndroidResources databindingProcessedResources = AndroidDataBindingProcessorBuilder.create(
-        dataContext,
-        resources,
-        appId,
-        DataBinding.getLayoutInfoFile(actionContext));
+    AndroidResources databindingProcessedResources =
+        AndroidDataBindingProcessorBuilder.create(
+            dataContext,
+            resources,
+            appId,
+            DataBinding.getLayoutInfoFile(actionContext),
+            useAndroidX);
 
     return databindingProcessedResources;
+  }
 
+  @Override
+  public boolean usesAndroidX() {
+    return useAndroidX;
   }
 
   private static Artifact getClassInfoFile(ActionConstructionContext context) {
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DisabledDataBindingV1Context.java b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DisabledDataBindingV1Context.java
index b0f859a..8e045df 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DisabledDataBindingV1Context.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DisabledDataBindingV1Context.java
@@ -71,4 +71,10 @@
   public void supplyLayoutInfo(Consumer<Artifact> consumer) {
 
   }
+
+  @Override
+  public boolean usesAndroidX() {
+    // AndroidX settings have no meaning if databinding is disabled.
+    return false;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DisabledDataBindingV2Context.java b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DisabledDataBindingV2Context.java
index 7c4127a..4a255db 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DisabledDataBindingV2Context.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/DisabledDataBindingV2Context.java
@@ -94,4 +94,10 @@
 
   @Override
   public void supplyLayoutInfo(Consumer<Artifact> consumer) {  }
+
+  @Override
+  public boolean usesAndroidX() {
+    // AndroidX settings have no meaning if databinding is disabled.
+    return false;
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/databinding_annotation_template_androidx.txt b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/databinding_annotation_template_androidx.txt
new file mode 100644
index 0000000..6625f52
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/databinding_annotation_template_androidx.txt
@@ -0,0 +1,13 @@
+package android.databinding.layouts;
+
+import androidx.databinding.BindingBuildInfo;
+
+/**
+ * Template for the file that feeds data binding's annotation processor. The
+ * processor reads the values set here to generate .java files that link XML
+ * data binding declarations (from layoutInfoDir) to app code.
+ */
+@BindingBuildInfo
+public class DataBindingInfo {
+  /* This only exists for annotation processing. */
+}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/android/databinding/databinding_annotation_template.txt b/src/main/java/com/google/devtools/build/lib/rules/android/databinding/databinding_annotation_template_support_lib.txt
similarity index 100%
rename from src/main/java/com/google/devtools/build/lib/rules/android/databinding/databinding_annotation_template.txt
rename to src/main/java/com/google/devtools/build/lib/rules/android/databinding/databinding_annotation_template_support_lib.txt
diff --git a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/android/AndroidConfigurationApi.java b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/android/AndroidConfigurationApi.java
index 5832df4..4141d4b 100644
--- a/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/android/AndroidConfigurationApi.java
+++ b/src/main/java/com/google/devtools/build/lib/starlarkbuildapi/android/AndroidConfigurationApi.java
@@ -215,6 +215,13 @@
   boolean useDataBindingUpdatedArgs();
 
   @StarlarkMethod(
+      name = "android_databinding_use_androidx",
+      structField = true,
+      doc = "",
+      documented = false)
+  boolean useDataBindingAndroidX();
+
+  @StarlarkMethod(
       name = "persistent_busybox_tools",
       structField = true,
       doc = "",
diff --git a/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java b/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
index 7d24bb8..c7bd424 100644
--- a/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
+++ b/src/test/java/com/google/devtools/build/lib/actions/util/ActionsTestUtil.java
@@ -714,23 +714,26 @@
     }
   }
 
-  /**
-   * Looks in the given artifacts Iterable for the first Artifact whose path ends with the given
-   * suffix and returns the Artifact.
-   */
+  /** Returns the first artifact found in the given set whose path ends with the given suffix. */
   public static Artifact getFirstArtifactEndingWith(
       NestedSet<? extends Artifact> artifacts, String suffix) {
     return getFirstArtifactEndingWith(artifacts.toList(), suffix);
   }
 
   /**
-   * Looks in the given artifacts Iterable for the first Artifact whose path ends with the given
-   * suffix and returns the Artifact.
+   * Returns the first artifact found in the given Iterable whose path ends with the given suffix.
    */
   public static Artifact getFirstArtifactEndingWith(
       Iterable<? extends Artifact> artifacts, String suffix) {
+    return getFirstArtifactMatching(
+        artifacts, artifact -> artifact.getExecPath().getPathString().endsWith(suffix));
+  }
+
+  /** Returns the first Artifact in the provided Iterable that matches the specified predicate. */
+  public static Artifact getFirstArtifactMatching(
+      Iterable<? extends Artifact> artifacts, Predicate<Artifact> predicate) {
     for (Artifact a : artifacts) {
-      if (a.getExecPath().getPathString().endsWith(suffix)) {
+      if (predicate.test(a)) {
         return a;
       }
     }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingV2Test.java b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingV2Test.java
index f1e973f..daa9101 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingV2Test.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/AndroidDataBindingV2Test.java
@@ -16,9 +16,11 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactMatching;
 import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.prettyArtifactNames;
 import static com.google.devtools.build.lib.rules.java.JavaCompileActionTestHelper.getJavacArguments;
 
+import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.actions.Artifact;
@@ -47,7 +49,7 @@
     useConfiguration("--experimental_android_databinding_v2");
   }
 
-  private void writeDataBindingFiles() throws Exception {
+  private void writeDataBindingLibrariesFiles() throws Exception {
 
     scratch.file(
         "java/android/library2/BUILD",
@@ -72,6 +74,11 @@
 
     scratch.file(
         "java/android/library/MyLib.java", "package android.library; public class MyLib {};");
+  }
+
+  private void writeDataBindingFiles() throws Exception {
+
+    writeDataBindingLibrariesFiles();
 
     scratch.file(
         "java/android/binary/BUILD",
@@ -127,6 +134,26 @@
         "java/android/binary/MyApp.java", "package android.binary; public class MyApp {};");
   }
 
+  private void writeDataBindingFilesWithShrinkage() throws Exception {
+
+    writeDataBindingLibrariesFiles();
+
+    scratch.file(
+        "java/android/binary/BUILD",
+        "android_binary(",
+        "    name = 'app',",
+        "    enable_data_binding = 1,",
+        "    manifest = 'AndroidManifest.xml',",
+        "    shrink_resources = 1,",
+        "    srcs = ['MyApp.java'],",
+        "    deps = ['//java/android/library:lib_with_databinding'],",
+        "    proguard_specs = ['proguard-spec.pro'],",
+        ")");
+
+    scratch.file(
+        "java/android/binary/MyApp.java", "package android.binary; public class MyApp {};");
+  }
+
   @Test
   public void basicDataBindingIntegration() throws Exception {
 
@@ -1043,4 +1070,170 @@
         ImmutableList.of("-Aandroid.databinding.directDependencyPkgs=[]");
     assertThat(getJavacArguments(binCompileAction)).containsAtLeastElementsIn(expectedJavacopts);
   }
+
+  @Test
+  public void dataBinding_aapt2PackageAction_withoutAndroidX_doesNotPassAndroidXFlag()
+      throws Exception {
+    useConfiguration(
+        "--experimental_android_databinding_v2", "--android_databinding_use_v3_4_args");
+    writeDataBindingFiles();
+
+    ConfiguredTarget ctapp = getConfiguredTarget("//java/android/binary:app");
+    Set<Artifact> allArtifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(ctapp));
+
+    Artifact aapt2PackageArtifact = getAapt2PackgeActionArtifact(allArtifacts);
+    assertThat(getGeneratingSpawnActionArgs(aapt2PackageArtifact))
+        .doesNotContain("--useDataBindingAndroidX");
+  }
+
+  @Test
+  public void dataBinding_aapt2PackageAction_withAndroidX_passesAndroidXFlag() throws Exception {
+    useConfiguration(
+        "--experimental_android_databinding_v2",
+        "--android_databinding_use_v3_4_args",
+        "--android_databinding_use_androidx");
+    writeDataBindingFiles();
+
+    ConfiguredTarget ctapp = getConfiguredTarget("//java/android/binary:app");
+    Set<Artifact> allArtifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(ctapp));
+
+    Artifact aapt2PackageArtifact = getAapt2PackgeActionArtifact(allArtifacts);
+    assertThat(getGeneratingSpawnActionArgs(aapt2PackageArtifact))
+        .contains("--useDataBindingAndroidX");
+  }
+
+  @Test
+  public void dataBinding_processingDatabindingAction_withoutAndroidX_doesNotPassAndroidXFlag()
+      throws Exception {
+    useConfiguration(
+        "--experimental_android_databinding_v2", "--android_databinding_use_v3_4_args");
+    writeDataBindingFiles();
+
+    ConfiguredTarget ctapp = getConfiguredTarget("//java/android/binary:app");
+    Set<Artifact> allArtifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(ctapp));
+
+    Artifact processingDatabindingArtifact = getProcessingDatabindingArtifact(allArtifacts);
+    assertThat(getGeneratingSpawnActionArgs(processingDatabindingArtifact))
+        .doesNotContain("--useDataBindingAndroidX");
+  }
+
+  @Test
+  public void dataBinding_processingDatabindingAction_withAndroidX_passesAndroidXFlag()
+      throws Exception {
+    useConfiguration(
+        "--experimental_android_databinding_v2",
+        "--android_databinding_use_v3_4_args",
+        "--android_databinding_use_androidx");
+    writeDataBindingFiles();
+
+    ConfiguredTarget ctapp = getConfiguredTarget("//java/android/binary:app");
+    Set<Artifact> allArtifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(ctapp));
+
+    Artifact processingDatabindingArtifact = getProcessingDatabindingArtifact(allArtifacts);
+    assertThat(getGeneratingSpawnActionArgs(processingDatabindingArtifact))
+        .contains("--useDataBindingAndroidX");
+  }
+
+  @Test
+  public void dataBinding_compileLibraryResourcesAction_withoutAndroidX_doesNotPassAndroidXFlag()
+      throws Exception {
+    useConfiguration(
+        "--experimental_android_databinding_v2", "--android_databinding_use_v3_4_args");
+    writeDataBindingFiles();
+
+    ConfiguredTarget ctapp = getConfiguredTarget("//java/android/binary:app");
+    Set<Artifact> allArtifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(ctapp));
+
+    Artifact compileLibraryResourcesArtifact = getCompileLibraryResourcesArtifact(allArtifacts);
+    assertThat(getGeneratingSpawnActionArgs(compileLibraryResourcesArtifact))
+        .doesNotContain("--useDataBindingAndroidX");
+  }
+
+  @Test
+  public void dataBinding_compileLibraryResourcesAction_withAndroidX_passesAndroidXFlag()
+      throws Exception {
+    useConfiguration(
+        "--experimental_android_databinding_v2",
+        "--android_databinding_use_v3_4_args",
+        "--android_databinding_use_androidx");
+    writeDataBindingFiles();
+
+    ConfiguredTarget ctapp = getConfiguredTarget("//java/android/binary:app");
+    Set<Artifact> allArtifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(ctapp));
+
+    Artifact compileLibraryResourcesArtifact = getCompileLibraryResourcesArtifact(allArtifacts);
+    assertThat(getGeneratingSpawnActionArgs(compileLibraryResourcesArtifact))
+        .contains("--useDataBindingAndroidX");
+  }
+
+  @Test
+  public void dataBinding_shrinkAapt2Action_withoutAndroidX_doesNotPassAndroidXFlag()
+      throws Exception {
+    useConfiguration(
+        "--experimental_android_databinding_v2", "--android_databinding_use_v3_4_args");
+    writeDataBindingFilesWithShrinkage();
+
+    ConfiguredTarget ctapp = getConfiguredTarget("//java/android/binary:app");
+    Set<Artifact> allArtifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(ctapp));
+
+    Artifact shrinkAapt2Artifact = getShrinkAapt2Artifact(allArtifacts);
+    assertThat(getGeneratingSpawnActionArgs(shrinkAapt2Artifact))
+        .doesNotContain("--useDataBindingAndroidX");
+  }
+
+  @Test
+  public void dataBinding_shrinkAapt2Action_withAndroidX_passesAndroidXFlag() throws Exception {
+    useConfiguration(
+        "--experimental_android_databinding_v2",
+        "--android_databinding_use_v3_4_args",
+        "--android_databinding_use_androidx");
+    writeDataBindingFilesWithShrinkage();
+
+    ConfiguredTarget ctapp = getConfiguredTarget("//java/android/binary:app");
+    Set<Artifact> allArtifacts = actionsTestUtil().artifactClosureOf(getFilesToBuild(ctapp));
+
+    Artifact shrinkAapt2Artifact = getShrinkAapt2Artifact(allArtifacts);
+    assertThat(getGeneratingSpawnActionArgs(shrinkAapt2Artifact))
+        .contains("--useDataBindingAndroidX");
+  }
+
+  private Artifact getAapt2PackgeActionArtifact(Set<Artifact> allArtifacts) {
+    return getArtifactForTool(allArtifacts, /* toolName= */ "AAPT2_PACKAGE");
+  }
+
+  private Artifact getProcessingDatabindingArtifact(Set<Artifact> allArtifacts) {
+    return getArtifactForTool(allArtifacts, /* toolName= */ "PROCESS_DATABINDING");
+  }
+
+  private Artifact getCompileLibraryResourcesArtifact(Set<Artifact> allArtifacts) {
+    return getArtifactForTool(allArtifacts, /* toolName= */ "COMPILE_LIBRARY_RESOURCES");
+  }
+
+  private Artifact getShrinkAapt2Artifact(Set<Artifact> allArtifacts) {
+    return getArtifactForTool(allArtifacts, /* toolName= */ "SHRINK_AAPT2");
+  }
+
+  private Artifact getArtifactForTool(Set<Artifact> allArtifacts, String toolName) {
+    Artifact artifact = getFirstArtifactMatching(allArtifacts, isSpawnActionWithTool(toolName));
+    assertWithMessage("Expected to find an artifact using tool: %s", toolName)
+        .that(artifact)
+        .isNotNull();
+    return artifact;
+  }
+
+  private Predicate<Artifact> isSpawnActionWithTool(String toolName) {
+    return artifact -> {
+      List<String> actionArgs;
+      try {
+        actionArgs = getGeneratingSpawnActionArgs(artifact);
+      } catch (Exception e) {
+        // Some artifacts are not compatible spawn artifacts.
+        return false;
+      }
+      int toolIndicatorIndex = actionArgs.indexOf("--tool");
+      return toolIndicatorIndex > -1
+          && toolIndicatorIndex + 1 < actionArgs.size()
+          && actionArgs.get(toolIndicatorIndex + 1).equals(toolName);
+    };
+  }
 }
diff --git a/src/test/java/com/google/devtools/build/lib/rules/android/BUILD b/src/test/java/com/google/devtools/build/lib/rules/android/BUILD
index 2a3dd4b..7b4e976 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/android/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/rules/android/BUILD
@@ -362,7 +362,6 @@
     tags = ["manual"],
     deps = [
         ":AndroidBuildViewTestCase",
-        "//src/main/java/com/google/devtools/build/lib/actions",
         "//src/main/java/com/google/devtools/build/lib/actions:artifacts",
         "//src/main/java/com/google/devtools/build/lib/analysis:configured_target",
         "//src/main/java/com/google/devtools/build/lib/cmdline",
diff --git a/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java b/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
index ce02a88..864276a 100644
--- a/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/Aapt2ResourcePackagingAction.java
@@ -328,7 +328,6 @@
         effectTags = {OptionEffectTag.NO_OP},
         help = "Unused/deprecated option.")
     public boolean isTestWithResources;
-
   }
 
   public static void main(String[] args) throws Exception {
@@ -369,7 +368,10 @@
           options
               .primaryData
               .processDataBindings(
-                  options.dataBindingInfoOut, options.packageForR, databindingResourcesRoot)
+                  options.dataBindingInfoOut,
+                  options.packageForR,
+                  databindingResourcesRoot,
+                  aaptConfigOptions.useDataBindingAndroidX)
               .compile(compiler, compiledResources)
               .processManifest(
                   manifest ->
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidDataBindingProcessingAction.java b/src/tools/android/java/com/google/devtools/build/android/AndroidDataBindingProcessingAction.java
index 6ff0baa..6fd7919 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidDataBindingProcessingAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidDataBindingProcessingAction.java
@@ -109,6 +109,7 @@
             .build();
     optionsParser.parseAndExitUponError(args);
     Options options = optionsParser.getOptions(Options.class);
+    AaptConfigOptions aaptConfigOptions = optionsParser.getOptions(AaptConfigOptions.class);
 
     if (options.dataBindingInfoOut == null) {
       throw new IllegalArgumentException("--dataBindingInfoOut is required");
@@ -137,7 +138,8 @@
             resourceRoot,
             dataBindingInfoOutDir.getPath(),
             options.appId,
-            /* shouldZipDataBindingInfo= */ false);
+            /* shouldZipDataBindingInfo= */ false,
+            aaptConfigOptions.useDataBindingAndroidX);
       }
 
       // 2. Zip all the layout info files into one zip file.
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
index 17d5bc4..c23031f 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
@@ -145,6 +145,15 @@
       help = "A list of resource config filters to pass to aapt."
     )
     public List<String> resourceConfigs;
+
+    @Option(
+        name = "useDataBindingAndroidX",
+        defaultValue = "false",
+        category = "config",
+        documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+        effectTags = {OptionEffectTag.UNKNOWN},
+        help = "Indicates whether databinding generated files should depend on AndroidX.")
+    public boolean useDataBindingAndroidX;
   }
 
   /** {@link AaptOptions} backed by an {@link AaptConfigOptions}. */
@@ -185,7 +194,7 @@
     this.stdLogger = stdLogger;
   }
 
-  // TODO(bazel-team): Clean up this method call -- 13 params is too many.
+  // TODO(bazel-team): Clean up this method call -- 18 params is too many.
   /**
    * Processes resources for generated sources, configs and packaging resources.
    *
@@ -202,6 +211,7 @@
       String customPackageForR,
       AaptOptions aaptOptions,
       Collection<String> resourceConfigs,
+      boolean useDataBindingAndroidX,
       MergedAndroidData primaryData,
       List<DependencyAndroidData> dependencyData,
       @Nullable Path sourceOut,
@@ -218,7 +228,8 @@
             primaryData.getResourceDir(),
             dataBindingInfoOut,
             customPackageForR,
-            /* shouldZipDataBindingInfo= */ true);
+            /* shouldZipDataBindingInfo= */ true,
+            useDataBindingAndroidX);
 
     final Path assetsDir = primaryData.getAssetDir();
     if (publicResourcesOut != null) {
@@ -251,7 +262,7 @@
     return new MergedAndroidData(resourceDir, assetsDir, androidManifest);
   }
 
-  public void runAapt(
+  private void runAapt(
       Path tempRoot,
       Path aapt,
       Path androidJar,
@@ -392,7 +403,8 @@
       Path inputResourcesDir,
       Path dataBindingInfoOut,
       String packagePath,
-      boolean shouldZipDataBindingInfo)
+      boolean shouldZipDataBindingInfo,
+      boolean useDataBindingAndroidX)
       throws IOException {
 
     if (dataBindingInfoOut == null) {
@@ -425,6 +437,7 @@
     options.setResInput(inputResourcesDir.toFile());
     options.setResOutput(processedResourceDir.toFile());
     options.setLayoutInfoOutput(dataBindingInfoOut.toFile());
+    options.setUseAndroidX(useDataBindingAndroidX);
     // Whether or not to aggregate data-bound .xml files into a single .zip.
     options.setZipLayoutInfo(shouldZipDataBindingInfo);
 
diff --git a/src/tools/android/java/com/google/devtools/build/android/CompileLibraryResourcesAction.java b/src/tools/android/java/com/google/devtools/build/android/CompileLibraryResourcesAction.java
index 3c14d72..5597ea1 100644
--- a/src/tools/android/java/com/google/devtools/build/android/CompileLibraryResourcesAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/CompileLibraryResourcesAction.java
@@ -97,7 +97,6 @@
               + " This value is required for processing data binding."
     )
     public Path dataBindingInfoOut;
-
   }
 
   static final Logger logger = Logger.getLogger(CompileLibraryResourcesAction.class.getName());
@@ -137,7 +136,10 @@
           .resources
           .toData(options.manifest)
           .processDataBindings(
-              options.dataBindingInfoOut, options.packagePath, databindingResourcesRoot)
+              options.dataBindingInfoOut,
+              options.packagePath,
+              databindingResourcesRoot,
+              aapt2Options.useDataBindingAndroidX)
           .compile(compiler, compiledResources)
           .copyResourcesZipTo(options.output);
     } catch (IOException | ExecutionException | InterruptedException e) {
diff --git a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
index 86691c9..e4e72fc 100644
--- a/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
+++ b/src/tools/android/java/com/google/devtools/build/android/ResourceShrinkerAction.java
@@ -307,16 +307,17 @@
           aaptConfigOptions.buildToolsVersion,
           VariantType.DEFAULT,
           aaptConfigOptions.debug,
-          null /* packageForR */,
+          /* customPackageForR= */ null,
           new FlagAaptOptions(aaptConfigOptions),
           aaptConfigOptions.resourceConfigs,
+          aaptConfigOptions.useDataBindingAndroidX,
           new MergedAndroidData(
               shrunkResources, resourceFiles.resolve("assets"), options.primaryManifest),
-          ImmutableList.<DependencyAndroidData>of() /* libraries */,
+          /* dependencyData= */ ImmutableList.<DependencyAndroidData>of(),
           generatedSources,
           options.shrunkApk,
-          null /* proguardOutput */,
-          null /* mainDexProguardOutput */,
+          /* proguardOut= */ null,
+          /* mainDexProguardOut= */ null,
           /* publicResourcesOut= */ null,
           /* dataBindingInfoOut= */ null);
       if (options.shrunkResources != null) {
diff --git a/src/tools/android/java/com/google/devtools/build/android/UnvalidatedAndroidData.java b/src/tools/android/java/com/google/devtools/build/android/UnvalidatedAndroidData.java
index fdc8fa6..d09402d 100644
--- a/src/tools/android/java/com/google/devtools/build/android/UnvalidatedAndroidData.java
+++ b/src/tools/android/java/com/google/devtools/build/android/UnvalidatedAndroidData.java
@@ -116,7 +116,10 @@
 
   /* Processes the resources for databinding annotations if dataBindingOut is defined. */
   public UnvalidatedAndroidData processDataBindings(
-      @Nullable Path dataBindingOut, String packagePath, Path dataBindingWorkingDirectory)
+      @Nullable Path dataBindingOut,
+      String packagePath,
+      Path dataBindingWorkingDirectory,
+      boolean useDataBindingAndroidX)
       throws IOException {
 
     if (dataBindingOut == null) {
@@ -137,7 +140,8 @@
               resource,
               metadataWorkingDirectory,
               packagePath,
-              false));
+              /* shouldZipDataBindingInfo= */ false,
+              useDataBindingAndroidX));
     }
 
     AndroidResourceOutputs.archiveDirectory(metadataWorkingDirectory, dataBindingOut);
diff --git a/src/tools/android/java/com/google/devtools/build/android/aapt2/Aapt2ConfigOptions.java b/src/tools/android/java/com/google/devtools/build/android/aapt2/Aapt2ConfigOptions.java
index f13dd3b..e82a522 100644
--- a/src/tools/android/java/com/google/devtools/build/android/aapt2/Aapt2ConfigOptions.java
+++ b/src/tools/android/java/com/google/devtools/build/android/aapt2/Aapt2ConfigOptions.java
@@ -164,4 +164,13 @@
       category = "config",
       help = "Whether to generate pseudo locales during compilation.")
   public boolean generatePseudoLocale;
+
+  @Option(
+      name = "useDataBindingAndroidX",
+      defaultValue = "false",
+      category = "config",
+      documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+      effectTags = {OptionEffectTag.UNKNOWN},
+      help = "Indicates whether databinding generated files should depend on AndroidX.")
+  public boolean useDataBindingAndroidX;
 }