binder: add openDeclaredPassthroughHal()

It handles dlopen()ing a declared native hal. This can replace
android_load_sphal_library to load declared native instance. The new API
also supports when instances are from APEX.

Bug: 316051788
Test: atest servicemanager_test
Test: atest vts_treble_vintf_vendor_test
Change-Id: I95b752253e0b550d38f0543ff56134d38d838855
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index ae0fb01..941e091 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -320,6 +320,24 @@
                 "ServiceManagerHost.cpp",
             ],
         },
+        android: {
+            shared_libs: [
+                "libapexsupport",
+                "libvndksupport",
+            ],
+        },
+        recovery: {
+            exclude_shared_libs: [
+                "libapexsupport",
+                "libvndksupport",
+            ],
+        },
+        native_bridge: {
+            exclude_shared_libs: [
+                "libapexsupport",
+                "libvndksupport",
+            ],
+        },
     },
     cflags: [
         "-DBINDER_WITH_KERNEL_IPC",
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index fe566fc..39573ec 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -40,6 +40,11 @@
 #include "ServiceManagerHost.h"
 #endif
 
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) && !defined(__ANDROID_NATIVE_BRIDGE__)
+#include <android/apexsupport.h>
+#include <vndksupport/linker.h>
+#endif
+
 #include "Static.h"
 
 namespace android {
@@ -259,6 +264,27 @@
     }
 }
 
+void* openDeclaredPassthroughHal(const String16& interface, const String16& instance, int flag) {
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) && !defined(__ANDROID_NATIVE_BRIDGE__)
+    sp<IServiceManager> sm = defaultServiceManager();
+    String16 name = interface + String16("/") + instance;
+    if (!sm->isDeclared(name)) {
+        return nullptr;
+    }
+    String16 libraryName = interface + String16(".") + instance + String16(".so");
+    if (auto updatableViaApex = sm->updatableViaApex(name); updatableViaApex.has_value()) {
+        return AApexSupport_loadLibrary(String8(libraryName).c_str(),
+                                        String8(*updatableViaApex).c_str(), flag);
+    }
+    return android_load_sphal_library(String8(libraryName).c_str(), flag);
+#else
+    (void)interface;
+    (void)instance;
+    (void)flag;
+    return nullptr;
+#endif
+}
+
 #endif //__ANDROID_VNDK__
 
 // ----------------------------------------------------------------------
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 55167a7..486bdfb 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -207,6 +207,8 @@
     return NAME_NOT_FOUND;
 }
 
+void* openDeclaredPassthroughHal(const String16& interface, const String16& instance, int flag);
+
 bool checkCallingPermission(const String16& permission);
 bool checkCallingPermission(const String16& permission,
                             int32_t* outPid, int32_t* outUid);
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 316a79c..b34b30d 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -243,6 +243,18 @@
         __INTRODUCED_IN(__ANDROID_API_U__);
 
 /**
+ * Opens a declared passthrough HAL.
+ *
+ * \param instance identifier of the passthrough service (e.g. "mapper")
+ * \param instance identifier of the implemenatation (e.g. "default")
+ * \param flag passed to dlopen()
+ */
+void* AServiceManager_openDeclaredPassthroughHal(const char* interface, const char* instance,
+                                                 int flag)
+        // TODO(b/302113279) use __INTRODUCED_LLNDK for vendor variants
+        __INTRODUCED_IN(__ANDROID_API_V__);
+
+/**
  * Prevent lazy services without client from shutting down their process
  *
  * This should only be used if it is every eventually set to false. If a
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 0843a8e..de624e4 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -204,6 +204,7 @@
     APersistableBundle_getDoubleVectorKeys;
     APersistableBundle_getStringVectorKeys;
     APersistableBundle_getPersistableBundleKeys;
+    AServiceManager_openDeclaredPassthroughHal; # systemapi llndk
 };
 
 LIBBINDER_NDK_PLATFORM {
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index 3bfdc59..5529455 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -200,6 +200,13 @@
         callback(String8(updatableViaApex.value()).c_str(), context);
     }
 }
+void* AServiceManager_openDeclaredPassthroughHal(const char* interface, const char* instance,
+                                                 int flag) {
+    LOG_ALWAYS_FATAL_IF(interface == nullptr, "interface == nullptr");
+    LOG_ALWAYS_FATAL_IF(instance == nullptr, "instance == nullptr");
+
+    return openDeclaredPassthroughHal(String16(interface), String16(instance), flag);
+}
 void AServiceManager_forceLazyServicesPersist(bool persist) {
     auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
     serviceRegistrar.forcePersist(persist);
diff --git a/libs/ui/Gralloc5.cpp b/libs/ui/Gralloc5.cpp
index c3b2d3d..123bef4 100644
--- a/libs/ui/Gralloc5.cpp
+++ b/libs/ui/Gralloc5.cpp
@@ -83,10 +83,18 @@
             return nullptr;
         }
 
-        std::string lib_name = "mapper." + mapperSuffix + ".so";
-        void *so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
+        void* so = nullptr;
+        // TODO(b/322384429) switch this to __ANDROID_API_V__ when V is finalized
+        // TODO(b/302113279) use __ANDROID_VENDOR_API__ for vendor variant
+        if (__builtin_available(android __ANDROID_API_FUTURE__, *)) {
+            so = AServiceManager_openDeclaredPassthroughHal("mapper", mapperSuffix.c_str(),
+                                                            RTLD_LOCAL | RTLD_NOW);
+        } else {
+            std::string lib_name = "mapper." + mapperSuffix + ".so";
+            so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
+        }
         if (!so) {
-            ALOGE("Failed to load %s", lib_name.c_str());
+            ALOGE("Failed to load mapper.%s.so", mapperSuffix.c_str());
         }
         return so;
     }();