Merge "Fix Bazel APEX wrapper to resolve symlinks of any number of levels."
diff --git a/rules/apex.bzl b/rules/apex.bzl
index 215ba80..32c216e 100644
--- a/rules/apex.bzl
+++ b/rules/apex.bzl
@@ -19,24 +19,31 @@
 load(":sh_binary.bzl", "ShBinaryInfo")
 load(":stripped_cc_common.bzl", "StrippedCcBinaryInfo")
 load(":android_app_certificate.bzl", "AndroidAppCertificateInfo")
-load("//build/bazel/rules/apex:transition.bzl", "apex_transition")
+load("//build/bazel/rules/apex:transition.bzl", "apex_transition", "shared_lib_transition_32", "shared_lib_transition_64")
 load("//build/bazel/rules/apex:cc.bzl", "ApexCcInfo", "apex_cc_aspect")
 
+DIR_LIB = "lib"
+DIR_LIB64 = "lib64"
+
 # Prepare the input files info for bazel_apexer_wrapper to generate APEX filesystem image.
 def _prepare_apexer_wrapper_inputs(ctx):
     # dictionary to return in the format:
     # apex_manifest[(image_file_dirname, image_file_basename)] = bazel_output_file
     apex_manifest = {}
 
-    # Handle native_shared_libs
-    for dep in ctx.attr.native_shared_libs:
-        apex_cc_info = dep[ApexCcInfo]
+    x86_constraint = ctx.attr._x86_constraint[platform_common.ConstraintValueInfo]
+    x86_64_constraint = ctx.attr._x86_64_constraint[platform_common.ConstraintValueInfo]
+    arm_constraint = ctx.attr._arm_constraint[platform_common.ConstraintValueInfo]
+    arm64_constraint = ctx.attr._arm64_constraint[platform_common.ConstraintValueInfo]
 
-        # TODO: Update apex_transition to split (1:4) the deps, one for each target platform
-        # Then ApexCcInfo would only return a single lib_files field
-
-        for lib_file in apex_cc_info.lib_files.to_list():
-            apex_manifest[("lib", lib_file.basename)] = lib_file
+    if ctx.target_platform_has_constraint(x86_constraint):
+        _add_libs_32_target(ctx, "x86", apex_manifest)
+    elif ctx.target_platform_has_constraint(x86_64_constraint):
+        _add_libs_64_target(ctx, "x86", "x86_64", apex_manifest)
+    elif ctx.target_platform_has_constraint(arm_constraint):
+        _add_libs_32_target(ctx, "arm", apex_manifest)
+    elif ctx.target_platform_has_constraint(arm64_constraint):
+        _add_libs_64_target(ctx, "arm", "arm64", apex_manifest)
 
     # Handle prebuilts
     for dep in ctx.attr.prebuilts:
@@ -92,6 +99,21 @@
 
     return apex_content_inputs, bazel_apexer_wrapper_manifest
 
+def _add_libs_32_target(ctx, key, apex_manifest):
+    if len(ctx.split_attr.native_shared_libs_32.keys()) > 0:
+        _add_lib_file(DIR_LIB, ctx.split_attr.native_shared_libs_32[key], apex_manifest)
+
+def _add_libs_64_target(ctx, key_32, key_64, apex_manifest):
+    _add_libs_32_target(ctx, key_32, apex_manifest)
+    if len(ctx.split_attr.native_shared_libs_64.keys()) > 0:
+        _add_lib_file(DIR_LIB64, ctx.split_attr.native_shared_libs_64[key_64], apex_manifest)
+
+def _add_lib_file(dir, libs, apex_manifest):
+    for dep in libs:
+        apex_cc_info = dep[ApexCcInfo]
+        for lib_file in apex_cc_info.transitive_shared_libs.to_list():
+            apex_manifest[(dir, lib_file.basename)] = lib_file
+
 # conv_apex_manifest - Convert the JSON APEX manifest to protobuf, which is needed by apexer.
 def _convert_apex_manifest_json_to_pb(ctx, apex_toolchain):
     apex_manifest_json = ctx.file.manifest
@@ -227,10 +249,17 @@
         "min_sdk_version": attr.string(),
         "updatable": attr.bool(default = True),
         "installable": attr.bool(default = True),
-        "native_shared_libs": attr.label_list(
+        "native_shared_libs_32": attr.label_list(
             providers = [ApexCcInfo],
             aspects = [apex_cc_aspect],
-            cfg = apex_transition,
+            cfg = shared_lib_transition_32,
+            doc = "The libs compiled for 32-bit",
+        ),
+        "native_shared_libs_64": attr.label_list(
+            providers = [ApexCcInfo],
+            aspects = [apex_cc_aspect],
+            cfg = shared_lib_transition_64,
+            doc = "The libs compiled for 64-bit",
         ),
         "binaries": attr.label_list(
             providers = [
@@ -255,8 +284,21 @@
             executable = True,
             default = "//build/make/tools/signapk",
         ),
+        "_x86_constraint": attr.label(
+            default = Label("//build/bazel/platforms/arch:x86"),
+        ),
+        "_x86_64_constraint": attr.label(
+            default = Label("//build/bazel/platforms/arch:x86_64"),
+        ),
+        "_arm_constraint": attr.label(
+            default = Label("//build/bazel/platforms/arch:arm"),
+        ),
+        "_arm64_constraint": attr.label(
+            default = Label("//build/bazel/platforms/arch:arm64"),
+        ),
     },
     toolchains = ["//build/bazel/rules/apex:apex_toolchain_type"],
+    fragments = ["platform"],
 )
 
 def apex(
@@ -269,7 +311,8 @@
         min_sdk_version = None,
         updatable = True,
         installable = True,
-        native_shared_libs = [],
+        native_shared_libs_32 = [],
+        native_shared_libs_64 = [],
         binaries = [],
         prebuilts = [],
         **kwargs):
@@ -290,7 +333,8 @@
         min_sdk_version = min_sdk_version,
         updatable = updatable,
         installable = installable,
-        native_shared_libs = native_shared_libs,
+        native_shared_libs_32 = native_shared_libs_32,
+        native_shared_libs_64 = native_shared_libs_64,
         binaries = binaries,
         prebuilts = prebuilts,
         **kwargs
diff --git a/rules/apex/cc.bzl b/rules/apex/cc.bzl
index a28c31a..ef1d3a5 100644
--- a/rules/apex/cc.bzl
+++ b/rules/apex/cc.bzl
@@ -17,13 +17,16 @@
 ApexCcInfo = provider(
     "Info needed to use CC targets in APEXes",
     fields = {
-        "lib_files": "File references to lib .so files produced by the CC target",
+        "transitive_shared_libs": "File references to transitive .so libs produced by the CC targets and should be included in the APEX.",
     },
 )
 
 def _apex_cc_aspect_impl(target, ctx):
     shared_object_files = []
 
+    # Transitive deps containing shared libraries to be propagated the apex.
+    transitive_deps = []
+
     # TODO(b/207812332): Filter out the ones with stable APIs
 
     # Exclude the stripped and unstripped so files
@@ -32,19 +35,22 @@
             if output_file.extension == "so":
                 shared_object_files.append(output_file)
         if hasattr(ctx.rule.attr, "shared"):
-            shared_object_files.extend(ctx.rule.attr.shared[ApexCcInfo].lib_files.to_list())
+            transitive_deps.append(ctx.rule.attr.shared)
     elif ctx.rule.kind == "cc_shared_library" and hasattr(ctx.rule.attr, "dynamic_deps"):
         # Propagate along the dynamic_deps edge
         for dep in ctx.rule.attr.dynamic_deps:
-            shared_object_files.extend(dep[ApexCcInfo].lib_files.to_list())
+            transitive_deps.append(dep)
     elif ctx.rule.kind == "stripped_shared_library" and hasattr(ctx.rule.attr, "src"):
         # Propagate along the src edge
-        shared_object_files = ctx.rule.attr.src[ApexCcInfo].lib_files.to_list()
+        transitive_deps.append(ctx.rule.attr.src)
 
     return [
         ApexCcInfo(
             # TODO: Rely on a split transition across arches to happen earlier
-            lib_files = depset(shared_object_files),
+            transitive_shared_libs = depset(
+                shared_object_files,
+                transitive = [dep[ApexCcInfo].transitive_shared_libs for dep in transitive_deps],
+            )
         ),
     ]
 
diff --git a/rules/apex/transition.bzl b/rules/apex/transition.bzl
index 6428d61..86d39cc 100644
--- a/rules/apex/transition.bzl
+++ b/rules/apex/transition.bzl
@@ -42,3 +42,61 @@
         "//build/bazel/rules/apex:min_sdk_version",
     ],
 )
+
+def _impl_shared_lib_transition_32(settings, attr):
+    # Perform a transition to apply APEX specific build settings on the
+    # destination target (i.e. an APEX dependency).
+
+    # TODO: We need to check if this is a x86 or arm arch then only set one platform
+    # instead of this 1:2 split to avoid performance hit.
+    return {
+        "x86": {
+            "//command_line_option:platforms": "//build/bazel/platforms:android_x86",
+            "//build/bazel/rules/apex:apex_name": attr.name,  # Name of the APEX
+            "//build/bazel/rules/apex:min_sdk_version": attr.min_sdk_version,  # Min SDK version of the APEX
+        },
+        "arm": {
+            "//command_line_option:platforms": "//build/bazel/platforms:android_arm",
+            "//build/bazel/rules/apex:apex_name": attr.name,  # Name of the APEX
+            "//build/bazel/rules/apex:min_sdk_version": attr.min_sdk_version,  # Min SDK version of the APEX
+        },
+    }
+
+shared_lib_transition_32 = transition(
+    implementation = _impl_shared_lib_transition_32,
+    inputs = [],
+    outputs = [
+        "//build/bazel/rules/apex:apex_name",
+        "//build/bazel/rules/apex:min_sdk_version",
+        "//command_line_option:platforms",
+    ],
+)
+
+def _impl_shared_lib_transition_64(settings, attr):
+    # Perform a transition to apply APEX specific build settings on the
+    # destination target (i.e. an APEX dependency).
+
+    # TODO: We need to check if this is a x86 or arm arch then only set one platform
+    # instead of this 1:2 split to avoid performance hit.
+    return {
+        "x86_64": {
+            "//command_line_option:platforms": "//build/bazel/platforms:android_x86_64",
+            "//build/bazel/rules/apex:apex_name": attr.name,  # Name of the APEX
+            "//build/bazel/rules/apex:min_sdk_version": attr.min_sdk_version,  # Min SDK version of the APEX
+        },
+        "arm64": {
+            "//command_line_option:platforms": "//build/bazel/platforms:android_arm64",
+            "//build/bazel/rules/apex:apex_name": attr.name,  # Name of the APEX
+            "//build/bazel/rules/apex:min_sdk_version": attr.min_sdk_version,  # Min SDK version of the APEX
+        },
+    }
+
+shared_lib_transition_64 = transition(
+    implementation = _impl_shared_lib_transition_64,
+    inputs = [],
+    outputs = [
+        "//build/bazel/rules/apex:apex_name",
+        "//build/bazel/rules/apex:min_sdk_version",
+        "//command_line_option:platforms",
+    ],
+)
diff --git a/tests/apex/expected_com.android.adbd b/tests/apex/expected_com.android.adbd
index e29cfdd..f942f36 100644
--- a/tests/apex/expected_com.android.adbd
+++ b/tests/apex/expected_com.android.adbd
@@ -1,10 +1,8 @@
-3a4,12
-> ./lib/libadb_pairing_auth.so
-> ./lib/libadb_pairing_connection.so
-> ./lib/libadb_pairing_server.so
-> ./lib/libadbconnection_client.so
-> ./lib/libbase.so
-> ./lib/libc++.so
-> ./lib/libcrypto.so
-> ./lib/libcrypto_utils.so
-> ./lib/libcutils.so
+4d3
+< ./lib/ld-android.so
+11d9
+< ./lib/libc.so
+15,17d12
+< ./lib/libdl.so
+< ./lib/liblog.so
+< ./lib/libm.so