Create a repo rule & module_extension for android sdk proxy

@android_external will be Bazel's direct dependency with dummy/falsy value. In android projects, define @android_external with each target pointing to android sdk content.

This is prerequisite to retire //external:android... in bazel/rules_android.

PiperOrigin-RevId: 611595652
Change-Id: I3f308b969b00d394b324c7cef789f79372a1583c
diff --git a/MODULE.bazel b/MODULE.bazel
index 83f6b34..eb2be76 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -362,3 +362,6 @@
 
 remote_android_extensions = use_extension("//tools/android:android_extensions.bzl", "remote_android_tools_extensions")
 use_repo(remote_android_extensions, "android_gmaven_r8", "android_tools")
+
+android_sdk_proxy_extensions = use_extension("//tools/android:android_extensions.bzl", "android_sdk_proxy_extensions")
+use_repo(android_sdk_proxy_extensions, "android_external")
diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock
index 2023e5a..e60d118 100644
--- a/MODULE.bazel.lock
+++ b/MODULE.bazel.lock
@@ -1,6 +1,6 @@
 {
   "lockFileVersion": 3,
-  "moduleFileHash": "979421da58e7667e2ced1ec085f90699cbd25925dae2bc3f83269c62c7be36c0",
+  "moduleFileHash": "ea0b5bfb8ce9d22dd6a775d23311d99ad1655deb9ce68dd4e4e07edf75bfd717",
   "flags": {
     "cmdRegistries": [
       "https://bcr.bazel.build/"
@@ -607,6 +607,23 @@
           "tags": [],
           "hasDevUseExtension": false,
           "hasNonDevUseExtension": true
+        },
+        {
+          "extensionBzlFile": "@io_bazel//tools/android:android_extensions.bzl",
+          "extensionName": "android_sdk_proxy_extensions",
+          "usingModule": "<root>",
+          "location": {
+            "file": "@@//:MODULE.bazel",
+            "line": 366,
+            "column": 45
+          },
+          "imports": {
+            "android_external": "android_external"
+          },
+          "devImports": [],
+          "tags": [],
+          "hasDevUseExtension": false,
+          "hasNonDevUseExtension": true
         }
       ],
       "deps": {
@@ -2748,8 +2765,8 @@
       "general": {
         "bzlTransitiveDigest": "r8gQnSLwon27gWD77J8mb3DIe4v3gtn7J/rsic53Qyw=",
         "accumulatedFileDigests": {
-          "@@//src/test/tools/bzlmod:MODULE.bazel.lock": "0b68adc1bedee1509b9d94dcb750cfc233deb2bb02276dab07c2b8ccf7b9213e",
-          "@@//:MODULE.bazel": "979421da58e7667e2ced1ec085f90699cbd25925dae2bc3f83269c62c7be36c0"
+          "@@//src/test/tools/bzlmod:MODULE.bazel.lock": "757d0a347552181528c083af9e8851fe4a0ca87ef21794f843fbfc2742cbfed1",
+          "@@//:MODULE.bazel": "ea0b5bfb8ce9d22dd6a775d23311d99ad1655deb9ce68dd4e4e07edf75bfd717"
         },
         "envVariables": {},
         "generatedRepoSpecs": {
@@ -3300,9 +3317,26 @@
         "recordedRepoMappingEntries": []
       }
     },
+    "//tools/android:android_extensions.bzl%android_sdk_proxy_extensions": {
+      "general": {
+        "bzlTransitiveDigest": "2AZ7StOD4EzjLI/J5lC8j+ezjzb6hAcRySycgrwBFRk=",
+        "accumulatedFileDigests": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "android_external": {
+            "bzlFile": "@@//tools/android:android_extensions.bzl",
+            "ruleClassName": "android_external_repository",
+            "attributes": {
+              "name": "_main~android_sdk_proxy_extensions~android_external"
+            }
+          }
+        },
+        "recordedRepoMappingEntries": []
+      }
+    },
     "//tools/android:android_extensions.bzl%remote_android_tools_extensions": {
       "general": {
-        "bzlTransitiveDigest": "vsrPPBNf8OgywAYLMcIL1oNm2R8WtbCIL9wgQBUecpA=",
+        "bzlTransitiveDigest": "2AZ7StOD4EzjLI/J5lC8j+ezjzb6hAcRySycgrwBFRk=",
         "accumulatedFileDigests": {},
         "envVariables": {},
         "generatedRepoSpecs": {
diff --git a/src/MODULE.tools b/src/MODULE.tools
index 2aa1919..cdeac29 100644
--- a/src/MODULE.tools
+++ b/src/MODULE.tools
@@ -43,6 +43,9 @@
 remote_android_extensions = use_extension("//tools/android:android_extensions.bzl", "remote_android_tools_extensions")
 use_repo(remote_android_extensions, "android_gmaven_r8", "android_tools")
 
+android_sdk_proxy_extensions = use_extension("//tools/android:android_extensions.bzl", "android_sdk_proxy_extensions")
+use_repo(android_sdk_proxy_extensions, "android_external")
+
 # Used by bazel mod tidy (see BazelModTidyFunction).
 buildozer_binary = use_extension("@buildozer//:buildozer_binary.bzl", "buildozer_binary")
 use_repo(buildozer_binary, "buildozer_binary")
diff --git a/src/test/tools/bzlmod/MODULE.bazel.lock b/src/test/tools/bzlmod/MODULE.bazel.lock
index 320e4fa..9d519af 100644
--- a/src/test/tools/bzlmod/MODULE.bazel.lock
+++ b/src/test/tools/bzlmod/MODULE.bazel.lock
@@ -13,7 +13,7 @@
     "compatibilityMode": "ERROR"
   },
   "localOverrideHashes": {
-    "bazel_tools": "1ae69322ac3823527337acf02016e8ee95813d8d356f47060255b8956fa642f0"
+    "bazel_tools": "e82a6b9d2289bd561deefe937f051155137c26d22da6fc1b01c1bdd59f3b393f"
   },
   "moduleDepGraph": {
     "<root>": {
@@ -150,12 +150,29 @@
           "hasNonDevUseExtension": true
         },
         {
+          "extensionBzlFile": "@bazel_tools//tools/android:android_extensions.bzl",
+          "extensionName": "android_sdk_proxy_extensions",
+          "usingModule": "bazel_tools@_",
+          "location": {
+            "file": "@@bazel_tools//:MODULE.bazel",
+            "line": 46,
+            "column": 45
+          },
+          "imports": {
+            "android_external": "android_external"
+          },
+          "devImports": [],
+          "tags": [],
+          "hasDevUseExtension": false,
+          "hasNonDevUseExtension": true
+        },
+        {
           "extensionBzlFile": "@buildozer//:buildozer_binary.bzl",
           "extensionName": "buildozer_binary",
           "usingModule": "bazel_tools@_",
           "location": {
             "file": "@@bazel_tools//:MODULE.bazel",
-            "line": 47,
+            "line": 50,
             "column": 33
           },
           "imports": {
@@ -1061,9 +1078,25 @@
         ]
       }
     },
+    "@@bazel_tools//tools/android:android_extensions.bzl%android_sdk_proxy_extensions": {
+      "general": {
+        "bzlTransitiveDigest": "2AZ7StOD4EzjLI/J5lC8j+ezjzb6hAcRySycgrwBFRk=",
+        "recordedFileInputs": {},
+        "recordedDirentsInputs": {},
+        "envVariables": {},
+        "generatedRepoSpecs": {
+          "android_external": {
+            "bzlFile": "@@bazel_tools//tools/android:android_extensions.bzl",
+            "ruleClassName": "android_external_repository",
+            "attributes": {}
+          }
+        },
+        "recordedRepoMappingEntries": []
+      }
+    },
     "@@bazel_tools//tools/android:android_extensions.bzl%remote_android_tools_extensions": {
       "general": {
-        "bzlTransitiveDigest": "vsrPPBNf8OgywAYLMcIL1oNm2R8WtbCIL9wgQBUecpA=",
+        "bzlTransitiveDigest": "2AZ7StOD4EzjLI/J5lC8j+ezjzb6hAcRySycgrwBFRk=",
         "recordedFileInputs": {},
         "recordedDirentsInputs": {},
         "envVariables": {},
diff --git a/tools/android/android_extensions.bzl b/tools/android/android_extensions.bzl
index 393234c..580c684 100644
--- a/tools/android/android_extensions.bzl
+++ b/tools/android/android_extensions.bzl
@@ -31,3 +31,82 @@
 remote_android_tools_extensions = module_extension(
     implementation = _remote_android_tools_extensions_impl,
 )
+
+def _android_external_repository_impl(repo_ctx):
+    repo_ctx.file(
+        "BUILD",
+        """
+alias(
+  name  = "has_androidsdk",
+  actual = "%s",
+  visibility = ["//visibility:public"],
+)
+alias(
+  name  = "dx_jar_import",
+  actual = "%s",
+  visibility = ["//visibility:public"],
+)
+alias(
+  name = "android_sdk_for_testing",
+  actual = "%s",
+  visibility = ["//visibility:public"],
+)
+alias(
+  name = "android_ndk_for_testing",
+  actual = "%s",
+  visibility = ["//visibility:public"],
+)
+""" % (
+            repo_ctx.attr.has_androidsdk,
+            repo_ctx.attr.dx_jar_import,
+            repo_ctx.attr.android_sdk_for_testing,
+            repo_ctx.attr.android_ndk_for_testing,
+        ),
+    )
+
+    pass
+
+android_external_repository = repository_rule(
+    implementation = _android_external_repository_impl,
+    attrs = {
+        "has_androidsdk": attr.label(default = "@bazel_tools//tools/android:always_false"),
+        "dx_jar_import": attr.label(default = "@bazel_tools//tools/android:no_android_sdk_repository_error"),
+        "android_sdk_for_testing": attr.label(default = "@bazel_tools//tools/android:empty"),
+        "android_ndk_for_testing": attr.label(default = "@bazel_tools//tools/android:empty"),
+    },
+    local = True,
+)
+
+def _android_sdk_proxy_extensions_impl(module_ctx):
+    root_modules = [m for m in module_ctx.modules if m.is_root]
+    if len(root_modules) > 1:
+        fail("Expected at most one root module, found {}".format(", ".join([x.name for x in root_modules])))
+
+    if root_modules:
+        module = root_modules[0]
+    else:
+        module = module_ctx.modules[0]
+
+    kwargs = {}
+    if module.tags.configure:
+        kwargs["has_androidsdk"] = module.tags.configure[0].has_androidsdk
+        kwargs["dx_jar_import"] = module.tags.configure[0].dx_jar_import
+        kwargs["android_sdk_for_testing"] = module.tags.configure[0].android_sdk_for_testing
+        kwargs["android_ndk_for_testing"] = module.tags.configure[0].android_ndk_for_testing
+
+    android_external_repository(
+        name = "android_external",
+        **kwargs
+    )
+
+android_sdk_proxy_extensions = module_extension(
+    implementation = _android_sdk_proxy_extensions_impl,
+    tag_classes = {
+        "configure": tag_class(attrs = {
+            "has_androidsdk": attr.label(default = "@bazel_tools//tools/android:always_false"),
+            "dx_jar_import": attr.label(default = "@bazel_tools//tools/android:no_android_sdk_repository_error"),
+            "android_sdk_for_testing": attr.label(default = "@bazel_tools//tools/android:empty"),
+            "android_ndk_for_testing": attr.label(default = "@bazel_tools//tools/android:empty"),
+        }),
+    },
+)