Implement NNAPI canonical interfaces
This CL implements the canonical IDevice, IPreparedModel, and IBuffer
interfaces for the 1.0, 1.1, 1.2, and 1.3 NN HIDL HAL interfaces.
Further, it introduces "Resilient" adapter interfaces to automatically
retrieve a handle to a recovered interface object after it has died and
rebooted.
This CL also updates the conversion code from returning nn::Result to
nn::GeneralResult, which includes a ErrorStatus code in the case of an
error.
Finally, this CL introduces a new static library
neuralnetworks_utils_hal_service which consists of a single function
::android::nn::hal::getDevices which can be used by the NNAPI runtime to
retrieve the HIDL services without knowing the underlying HIDL types.
Bug: 160668438
Test: mma
Test: NeuralNetworksTest_static
Change-Id: Iec6ae739df196b4034ffb35ea76781fd541ffec3
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
index 667189b..2565972 100644
--- a/neuralnetworks/utils/common/src/CommonUtils.cpp
+++ b/neuralnetworks/utils/common/src/CommonUtils.cpp
@@ -16,6 +16,8 @@
#include "CommonUtils.h"
+#include "HandleError.h"
+
#include <android-base/logging.h>
#include <nnapi/Result.h>
#include <nnapi/SharedMemory.h>
@@ -25,6 +27,7 @@
#include <algorithm>
#include <any>
+#include <functional>
#include <optional>
#include <variant>
#include <vector>
@@ -111,8 +114,18 @@
return hasNoPointerData(request.inputs) && hasNoPointerData(request.outputs);
}
-nn::Result<nn::Model> flushDataFromPointerToShared(const nn::Model& model) {
- auto modelInShared = model;
+nn::GeneralResult<std::reference_wrapper<const nn::Model>> flushDataFromPointerToShared(
+ const nn::Model* model, std::optional<nn::Model>* maybeModelInSharedOut) {
+ CHECK(model != nullptr);
+ CHECK(maybeModelInSharedOut != nullptr);
+
+ if (hasNoPointerData(*model)) {
+ return *model;
+ }
+
+ // Make a copy of the model in order to make modifications. The modified model is returned to
+ // the caller through `maybeModelInSharedOut` if the function succeeds.
+ nn::Model modelInShared = *model;
nn::ConstantMemoryBuilder memoryBuilder(modelInShared.pools.size());
copyPointersToSharedMemory(&modelInShared.main, &memoryBuilder);
@@ -126,11 +139,22 @@
modelInShared.pools.push_back(std::move(memory));
}
- return modelInShared;
+ *maybeModelInSharedOut = modelInShared;
+ return **maybeModelInSharedOut;
}
-nn::Result<nn::Request> flushDataFromPointerToShared(const nn::Request& request) {
- auto requestInShared = request;
+nn::GeneralResult<std::reference_wrapper<const nn::Request>> flushDataFromPointerToShared(
+ const nn::Request* request, std::optional<nn::Request>* maybeRequestInSharedOut) {
+ CHECK(request != nullptr);
+ CHECK(maybeRequestInSharedOut != nullptr);
+
+ if (hasNoPointerData(*request)) {
+ return *request;
+ }
+
+ // Make a copy of the request in order to make modifications. The modified request is returned
+ // to the caller through `maybeRequestInSharedOut` if the function succeeds.
+ nn::Request requestInShared = *request;
// Change input pointers to shared memory.
nn::ConstantMemoryBuilder inputBuilder(requestInShared.pools.size());
@@ -171,15 +195,17 @@
requestInShared.pools.push_back(std::move(memory));
}
- return requestInShared;
+ *maybeRequestInSharedOut = requestInShared;
+ return **maybeRequestInSharedOut;
}
-nn::Result<void> unflushDataFromSharedToPointer(const nn::Request& request,
- const nn::Request& requestInShared) {
- if (requestInShared.pools.empty() ||
- !std::holds_alternative<nn::Memory>(requestInShared.pools.back())) {
+nn::GeneralResult<void> unflushDataFromSharedToPointer(
+ const nn::Request& request, const std::optional<nn::Request>& maybeRequestInShared) {
+ if (!maybeRequestInShared.has_value() || maybeRequestInShared->pools.empty() ||
+ !std::holds_alternative<nn::Memory>(maybeRequestInShared->pools.back())) {
return {};
}
+ const auto& requestInShared = *maybeRequestInShared;
// Map the memory.
const auto& outputMemory = std::get<nn::Memory>(requestInShared.pools.back());