NNAPI: Add AIDL drivers registration

Bug: 179015258
Test: adb shell setprop debug.nn.partition 2 && \
Test: NeuralNetworksTest_static
Change-Id: I2c8c9a49ff917b243348043df1158a8d98f131ce
Merged-In: I2c8c9a49ff917b243348043df1158a8d98f131ce
(cherry picked from commit 5f732ff683211e14bcb489839e46b99ee4c39106)
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
index b4587ac..cb6ff4b 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Service.h
@@ -20,13 +20,12 @@
 #include <nnapi/IDevice.h>
 #include <nnapi/Result.h>
 #include <nnapi/Types.h>
-#include <nnapi/hal/CommonUtils.h>
 
 #include <string>
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
-nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name);
+::android::nn::GeneralResult<::android::nn::SharedDevice> getDevice(const std::string& name);
 
 }  // namespace aidl::android::hardware::neuralnetworks::utils
 
diff --git a/neuralnetworks/aidl/utils/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp
index 5ec6ded..511de55 100644
--- a/neuralnetworks/aidl/utils/src/Service.cpp
+++ b/neuralnetworks/aidl/utils/src/Service.cpp
@@ -18,6 +18,7 @@
 
 #include <android/binder_auto_utils.h>
 #include <android/binder_manager.h>
+#include <android/binder_process.h>
 
 #include <nnapi/IDevice.h>
 #include <nnapi/Result.h>
@@ -29,19 +30,21 @@
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 
-nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& name) {
+nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& instanceName) {
+    auto fullName = std::string(IDevice::descriptor) + "/" + instanceName;
     hal::utils::ResilientDevice::Factory makeDevice =
-            [name](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
-        auto service = blocking ? IDevice::fromBinder(
-                                          ndk::SpAIBinder(AServiceManager_getService(name.c_str())))
-                                : IDevice::fromBinder(ndk::SpAIBinder(
-                                          AServiceManager_checkService(name.c_str())));
+            [instanceName,
+             name = std::move(fullName)](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
+        const auto& getService =
+                blocking ? AServiceManager_getService : AServiceManager_checkService;
+        auto service = IDevice::fromBinder(ndk::SpAIBinder(getService(name.c_str())));
         if (service == nullptr) {
             return NN_ERROR() << (blocking ? "AServiceManager_getService"
                                            : "AServiceManager_checkService")
                               << " returned nullptr";
         }
-        return Device::create(name, std::move(service));
+        ABinderProcess_startThreadPool();
+        return Device::create(instanceName, std::move(service));
     };
 
     return hal::utils::ResilientDevice::create(std::move(makeDevice));
diff --git a/neuralnetworks/utils/service/Android.bp b/neuralnetworks/utils/service/Android.bp
index 9f8b9bb..5f36dff 100644
--- a/neuralnetworks/utils/service/Android.bp
+++ b/neuralnetworks/utils/service/Android.bp
@@ -35,12 +35,15 @@
         "neuralnetworks_utils_hal_1_1",
         "neuralnetworks_utils_hal_1_2",
         "neuralnetworks_utils_hal_1_3",
+        "neuralnetworks_utils_hal_aidl",
         "neuralnetworks_utils_hal_common",
     ],
     shared_libs: [
+        "android.hardware.neuralnetworks-V1-ndk_platform",
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
         "android.hardware.neuralnetworks@1.3",
+        "libbinder_ndk",
     ],
 }
diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp
index a59549d..c83bcc9 100644
--- a/neuralnetworks/utils/service/src/Service.cpp
+++ b/neuralnetworks/utils/service/src/Service.cpp
@@ -16,7 +16,9 @@
 
 #include "Service.h"
 
+#include <aidl/android/hardware/neuralnetworks/IDevice.h>
 #include <android-base/logging.h>
+#include <android/binder_manager.h>
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
 #include <android/hardware/neuralnetworks/1.1/IDevice.h>
 #include <android/hardware/neuralnetworks/1.2/IDevice.h>
@@ -31,6 +33,7 @@
 #include <nnapi/hal/1.1/Service.h>
 #include <nnapi/hal/1.2/Service.h>
 #include <nnapi/hal/1.3/Service.h>
+#include <nnapi/hal/aidl/Service.h>
 
 #include <functional>
 #include <memory>
@@ -42,11 +45,12 @@
 namespace android::hardware::neuralnetworks::service {
 namespace {
 
+namespace aidl_hal = ::aidl::android::hardware::neuralnetworks;
 using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>;
 
-void getDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
-                          std::vector<nn::SharedDevice>* devices,
-                          std::unordered_set<std::string>* registeredDevices) {
+void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
+                              std::vector<nn::SharedDevice>* devices,
+                              std::unordered_set<std::string>* registeredDevices) {
     CHECK(devices != nullptr);
     CHECK(registeredDevices != nullptr);
 
@@ -66,18 +70,52 @@
     }
 }
 
+void getAidlDevices(std::vector<nn::SharedDevice>* devices,
+                    std::unordered_set<std::string>* registeredDevices) {
+    CHECK(devices != nullptr);
+    CHECK(registeredDevices != nullptr);
+
+    std::vector<std::string> names;
+    constexpr auto callback = [](const char* serviceName, void* names) {
+        static_cast<std::vector<std::string>*>(names)->emplace_back(serviceName);
+    };
+
+    // Devices with SDK level lower than 31 (Android S) don't have any AIDL drivers available, so
+    // there is no need for a workaround supported on lower levels.
+    if (__builtin_available(android __ANDROID_API_S__, *)) {
+        AServiceManager_forEachDeclaredInstance(aidl_hal::IDevice::descriptor,
+                                                static_cast<void*>(&names), callback);
+    }
+
+    for (const auto& name : names) {
+        if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
+            auto maybeDevice = aidl_hal::utils::getDevice(name);
+            if (maybeDevice.has_value()) {
+                auto device = std::move(maybeDevice).value();
+                CHECK(device != nullptr);
+                devices->push_back(std::move(device));
+            } else {
+                LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
+                           << ": " << maybeDevice.error().message;
+            }
+        }
+    }
+}
+
 std::vector<nn::SharedDevice> getDevices() {
     std::vector<nn::SharedDevice> devices;
     std::unordered_set<std::string> registeredDevices;
 
-    getDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
-                         &registeredDevices);
-    getDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices,
-                         &registeredDevices);
-    getDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices,
-                         &registeredDevices);
-    getDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices,
-                         &registeredDevices);
+    getAidlDevices(&devices, &registeredDevices);
+
+    getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
+                             &registeredDevices);
+    getHidlDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices,
+                             &registeredDevices);
+    getHidlDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices,
+                             &registeredDevices);
+    getHidlDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices,
+                             &registeredDevices);
 
     return devices;
 }