Move NN memory utils from utils/common to 1.0/utils
This change is part of a larger chain of changes to remove HIDL and AIDL
libraries from neuralnetworks_utils_hal_common.
Bug: N/A
Test: mma
Change-Id: I9d4f0c30932fad7ccb6231aa03e57f7227af4880
diff --git a/neuralnetworks/1.0/utils/Android.bp b/neuralnetworks/1.0/utils/Android.bp
index 8c51c67..31cdded 100644
--- a/neuralnetworks/1.0/utils/Android.bp
+++ b/neuralnetworks/1.0/utils/Android.bp
@@ -31,6 +31,7 @@
export_include_dirs: ["include"],
cflags: ["-Wthread-safety"],
static_libs: [
+ "libarect",
"neuralnetworks_types",
"neuralnetworks_utils_hal_common",
],
@@ -40,6 +41,11 @@
export_static_lib_headers: [
"neuralnetworks_utils_hal_common",
],
+ target: {
+ android: {
+ shared_libs: ["libnativewindow"],
+ },
+ },
}
cc_test {
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
index 5d4bdbc..a770d06 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Conversions.h
@@ -36,6 +36,7 @@
GeneralResult<Operation> unvalidatedConvert(const hal::V1_0::Operation& operation);
GeneralResult<Model::OperandValues> unvalidatedConvert(
const hardware::hidl_vec<uint8_t>& operandValues);
+GeneralResult<SharedHandle> unvalidatedConvert(const hardware::hidl_handle& handle);
GeneralResult<SharedMemory> unvalidatedConvert(const hardware::hidl_memory& memory);
GeneralResult<Model> unvalidatedConvert(const hal::V1_0::Model& model);
GeneralResult<Request::Argument> unvalidatedConvert(
@@ -65,6 +66,7 @@
nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation);
nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
const nn::Model::OperandValues& operandValues);
+nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle);
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory);
nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model);
nn::GeneralResult<RequestArgument> unvalidatedConvert(const nn::Request::Argument& requestArgument);
diff --git a/neuralnetworks/1.0/utils/src/Conversions.cpp b/neuralnetworks/1.0/utils/src/Conversions.cpp
index 9270870..daa10fd 100644
--- a/neuralnetworks/1.0/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.0/utils/src/Conversions.cpp
@@ -37,6 +37,11 @@
#include "Utils.h"
+#ifdef __ANDROID__
+#include <android/hardware_buffer.h>
+#include <vndk/hardware_buffer.h>
+#endif // __ANDROID__
+
namespace {
template <typename Type>
@@ -49,6 +54,7 @@
namespace android::nn {
namespace {
+using hardware::hidl_handle;
using hardware::hidl_memory;
using hardware::hidl_vec;
@@ -74,6 +80,121 @@
return canonical;
}
+nn::GeneralResult<nn::Memory::Unknown::Handle> unknownHandleFromNativeHandle(
+ const native_handle_t* handle) {
+ if (handle == nullptr) {
+ return NN_ERROR() << "unknownHandleFromNativeHandle failed because handle is nullptr";
+ }
+
+ std::vector<base::unique_fd> fds =
+ NN_TRY(nn::dupFds(handle->data + 0, handle->data + handle->numFds));
+
+ std::vector<int> ints(handle->data + handle->numFds,
+ handle->data + handle->numFds + handle->numInts);
+
+ return nn::Memory::Unknown::Handle{.fds = std::move(fds), .ints = std::move(ints)};
+}
+
+nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory) {
+ CHECK_LE(memory.size(), std::numeric_limits<size_t>::max());
+ if (!memory.valid()) {
+ return NN_ERROR() << "Unable to convert invalid hidl_memory";
+ }
+
+ if (memory.name() == "ashmem") {
+ if (memory.handle()->numFds != 1) {
+ return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
+ << memory.handle()->numFds << " numFds, but expected 1";
+ }
+ if (memory.handle()->numInts != 0) {
+ return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
+ << memory.handle()->numInts << " numInts, but expected 0";
+ }
+ auto handle = nn::Memory::Ashmem{
+ .fd = NN_TRY(nn::dupFd(memory.handle()->data[0])),
+ .size = static_cast<size_t>(memory.size()),
+ };
+ return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
+ }
+
+ if (memory.name() == "mmap_fd") {
+ if (memory.handle()->numFds != 1) {
+ return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
+ << memory.handle()->numFds << " numFds, but expected 1";
+ }
+ if (memory.handle()->numInts != 3) {
+ return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
+ << memory.handle()->numInts << " numInts, but expected 3";
+ }
+
+ const int fd = memory.handle()->data[0];
+ const int prot = memory.handle()->data[1];
+ const int lower = memory.handle()->data[2];
+ const int higher = memory.handle()->data[3];
+ const size_t offset = nn::getOffsetFromInts(lower, higher);
+
+ return nn::createSharedMemoryFromFd(static_cast<size_t>(memory.size()), prot, fd, offset);
+ }
+
+ if (memory.name() != "hardware_buffer_blob") {
+ auto handle = nn::Memory::Unknown{
+ .handle = NN_TRY(unknownHandleFromNativeHandle(memory.handle())),
+ .size = static_cast<size_t>(memory.size()),
+ .name = memory.name(),
+ };
+ return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
+ }
+
+#ifdef __ANDROID__
+ constexpr auto roundUpToMultiple = [](uint32_t value, uint32_t multiple) -> uint32_t {
+ return (value + multiple - 1) / multiple * multiple;
+ };
+
+ const auto size = memory.size();
+ const auto format = AHARDWAREBUFFER_FORMAT_BLOB;
+ const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+ const uint32_t width = size;
+ const uint32_t height = 1; // height is always 1 for BLOB mode AHardwareBuffer.
+ const uint32_t layers = 1; // layers is always 1 for BLOB mode AHardwareBuffer.
+
+ // AHardwareBuffer_createFromHandle() might fail because an allocator
+ // expects a specific stride value. In that case, we try to guess it by
+ // aligning the width to small powers of 2.
+ // TODO(b/174120849): Avoid stride assumptions.
+ AHardwareBuffer* hardwareBuffer = nullptr;
+ status_t status = UNKNOWN_ERROR;
+ for (uint32_t alignment : {1, 4, 32, 64, 128, 2, 8, 16}) {
+ const uint32_t stride = roundUpToMultiple(width, alignment);
+ AHardwareBuffer_Desc desc{
+ .width = width,
+ .height = height,
+ .layers = layers,
+ .format = format,
+ .usage = usage,
+ .stride = stride,
+ };
+ status = AHardwareBuffer_createFromHandle(&desc, memory.handle(),
+ AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
+ &hardwareBuffer);
+ if (status == NO_ERROR) {
+ break;
+ }
+ }
+ if (status != NO_ERROR) {
+ return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+ << "Can't create AHardwareBuffer from handle. Error: " << status;
+ }
+
+ return nn::createSharedMemoryFromAHWB(hardwareBuffer, /*takeOwnership=*/true);
+#else // __ANDROID__
+ LOG(FATAL) << "nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const "
+ "hidl_memory& memory): Not Available on Host Build";
+ return (NN_ERROR() << "createSharedMemoryFromHidlMemory failed")
+ .
+ operator nn::GeneralResult<nn::SharedMemory>();
+#endif // __ANDROID__
+}
+
} // anonymous namespace
GeneralResult<OperandType> unvalidatedConvert(const hal::V1_0::OperandType& operandType) {
@@ -146,8 +267,20 @@
return Model::OperandValues(operandValues.data(), operandValues.size());
}
+GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& handle) {
+ if (handle.getNativeHandle() == nullptr) {
+ return nullptr;
+ }
+ if (handle->numFds != 1 || handle->numInts != 0) {
+ return NN_ERROR()
+ << "unvalidatedConvert failed because handle does not only hold a single fd";
+ }
+ auto duplicatedFd = NN_TRY(nn::dupFd(handle->data[0]));
+ return std::make_shared<const Handle>(std::move(duplicatedFd));
+}
+
GeneralResult<SharedMemory> unvalidatedConvert(const hidl_memory& memory) {
- return hal::utils::createSharedMemoryFromHidlMemory(memory);
+ return createSharedMemoryFromHidlMemory(memory);
}
GeneralResult<Model> unvalidatedConvert(const hal::V1_0::Model& model) {
@@ -260,6 +393,82 @@
return utils::unvalidatedConvert(canonical);
}
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(std::vector<base::unique_fd> fds,
+ const std::vector<int32_t>& ints) {
+ constexpr size_t kIntMax = std::numeric_limits<int>::max();
+ CHECK_LE(fds.size(), kIntMax);
+ CHECK_LE(ints.size(), kIntMax);
+ native_handle_t* nativeHandle =
+ native_handle_create(static_cast<int>(fds.size()), static_cast<int>(ints.size()));
+ if (nativeHandle == nullptr) {
+ return NN_ERROR() << "Failed to create native_handle";
+ }
+
+ for (size_t i = 0; i < fds.size(); ++i) {
+ nativeHandle->data[i] = fds[i].release();
+ }
+ std::copy(ints.begin(), ints.end(), nativeHandle->data + nativeHandle->numFds);
+
+ hidl_handle handle;
+ handle.setTo(nativeHandle, /*shouldOwn=*/true);
+ return handle;
+}
+
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(base::unique_fd fd,
+ const std::vector<int32_t>& ints) {
+ std::vector<base::unique_fd> fds;
+ fds.push_back(std::move(fd));
+ return createNativeHandleFrom(std::move(fds), ints);
+}
+
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(const nn::Memory::Unknown::Handle& handle) {
+ std::vector<base::unique_fd> fds = NN_TRY(nn::dupFds(handle.fds.begin(), handle.fds.end()));
+ return createNativeHandleFrom(std::move(fds), handle.ints);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Ashmem& memory) {
+ auto fd = NN_TRY(nn::dupFd(memory.fd));
+ auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), {}));
+ return hidl_memory("ashmem", std::move(handle), memory.size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Fd& memory) {
+ auto fd = NN_TRY(nn::dupFd(memory.fd));
+
+ const auto [lowOffsetBits, highOffsetBits] = nn::getIntsFromOffset(memory.offset);
+ const std::vector<int> ints = {memory.prot, lowOffsetBits, highOffsetBits};
+
+ auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), ints));
+ return hidl_memory("mmap_fd", std::move(handle), memory.size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::HardwareBuffer& memory) {
+#ifdef __ANDROID__
+ const auto* ahwb = memory.handle.get();
+ AHardwareBuffer_Desc bufferDesc;
+ AHardwareBuffer_describe(ahwb, &bufferDesc);
+
+ const bool isBlob = bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB;
+ const size_t size = isBlob ? bufferDesc.width : 0;
+ const char* const name = isBlob ? "hardware_buffer_blob" : "hardware_buffer";
+
+ const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
+ const hidl_handle hidlHandle(nativeHandle);
+ hidl_handle copiedHandle(hidlHandle);
+
+ return hidl_memory(name, std::move(copiedHandle), size);
+#else // __ANDROID__
+ LOG(FATAL) << "nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const "
+ "nn::Memory::HardwareBuffer& memory): Not Available on Host Build";
+ (void)memory;
+ return (NN_ERROR() << "createHidlMemoryFrom failed").operator nn::GeneralResult<hidl_memory>();
+#endif // __ANDROID__
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Unknown& memory) {
+ return hidl_memory(memory.name, NN_TRY(createNativeHandleFrom(memory.handle)), memory.size);
+}
+
} // anonymous namespace
nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
@@ -332,8 +541,19 @@
return hidl_vec<uint8_t>(operandValues.data(), operandValues.data() + operandValues.size());
}
+nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
+ if (handle == nullptr) {
+ return {};
+ }
+ base::unique_fd fd = NN_TRY(nn::dupFd(handle->get()));
+ return createNativeHandleFrom(std::move(fd), {});
+}
+
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
- return hal::utils::createHidlMemoryFromSharedMemory(memory);
+ if (memory == nullptr) {
+ return NN_ERROR() << "Memory must be non-empty";
+ }
+ return std::visit([](const auto& x) { return createHidlMemoryFrom(x); }, memory->handle);
}
nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
index 272cee7..c3348aa 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
@@ -45,7 +45,6 @@
GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension);
GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation);
-GeneralResult<SharedHandle> unvalidatedConvert(const hardware::hidl_handle& handle);
GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType);
GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities);
@@ -86,7 +85,6 @@
nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension);
nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
const nn::Extension::OperandTypeInformation& operandTypeInformation);
-nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle);
nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType);
nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities);
diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp
index c8e83a2..ef5056b 100644
--- a/neuralnetworks/1.2/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.2/utils/src/Conversions.cpp
@@ -264,14 +264,6 @@
};
}
-GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) {
- if (hidlHandle.getNativeHandle() == nullptr) {
- return nullptr;
- }
- auto handle = NN_TRY(hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle()));
- return std::make_shared<const Handle>(std::move(handle));
-}
-
GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
return validatedConvert(deviceType);
}
@@ -334,6 +326,10 @@
return V1_0::utils::unvalidatedConvert(operandValues);
}
+nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
+ return V1_0::utils::unvalidatedConvert(handle);
+}
+
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
return V1_0::utils::unvalidatedConvert(memory);
}
@@ -544,13 +540,6 @@
};
}
-nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
- if (handle == nullptr) {
- return {};
- }
- return hal::utils::hidlHandleFromSharedHandle(*handle);
-}
-
nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
return validatedConvert(deviceType);
}
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
index b677c62..ec1e530 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
@@ -113,6 +113,9 @@
nn::GeneralResult<V1_2::MeasureTiming> convert(const nn::MeasureTiming& measureTiming);
nn::GeneralResult<V1_2::Timing> convert(const nn::Timing& timing);
+nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
+ const std::vector<nn::SyncFence>& fences);
+
} // namespace android::hardware::neuralnetworks::V1_3::utils
#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_CONVERSIONS_H
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index 74d8938..c885d60 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -380,7 +380,7 @@
}
nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
- return V1_2::utils::unvalidatedConvert(handle);
+ return V1_0::utils::unvalidatedConvert(handle);
}
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
@@ -727,4 +727,13 @@
return V1_2::utils::convert(timing);
}
+nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
+ const std::vector<nn::SyncFence>& syncFences) {
+ std::vector<nn::SharedHandle> handles;
+ handles.reserve(syncFences.size());
+ std::transform(syncFences.begin(), syncFences.end(), std::back_inserter(handles),
+ [](const nn::SyncFence& syncFence) { return syncFence.getSharedHandle(); });
+ return convert(handles);
+}
+
} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/Execution.cpp b/neuralnetworks/1.3/utils/src/Execution.cpp
index 4dc0ddf..467d87d 100644
--- a/neuralnetworks/1.3/utils/src/Execution.cpp
+++ b/neuralnetworks/1.3/utils/src/Execution.cpp
@@ -73,7 +73,7 @@
nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> Execution::computeFenced(
const std::vector<nn::SyncFence>& waitFor, const nn::OptionalTimePoint& deadline,
const nn::OptionalDuration& timeoutDurationAfterFence) const {
- const auto hidlWaitFor = NN_TRY(hal::utils::convertSyncFences(waitFor));
+ const auto hidlWaitFor = NN_TRY(convertSyncFences(waitFor));
const auto hidlDeadline = NN_TRY(convert(deadline));
const auto hidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
return kPreparedModel->executeFencedInternal(kRequest, hidlWaitFor, kMeasure, hidlDeadline,
diff --git a/neuralnetworks/1.3/utils/src/PreparedModel.cpp b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
index d5dee9d..c9771e3 100644
--- a/neuralnetworks/1.3/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
@@ -186,7 +186,7 @@
&maybeRequestInShared, &relocation));
const auto hidlRequest = NN_TRY(convert(requestInShared));
- const auto hidlWaitFor = NN_TRY(hal::utils::convertSyncFences(waitFor));
+ const auto hidlWaitFor = NN_TRY(convertSyncFences(waitFor));
const auto hidlMeasure = NN_TRY(convert(measure));
const auto hidlDeadline = NN_TRY(convert(deadline));
const auto hidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
diff --git a/neuralnetworks/utils/common/Android.bp b/neuralnetworks/utils/common/Android.bp
index f88e407..6f07be9 100644
--- a/neuralnetworks/utils/common/Android.bp
+++ b/neuralnetworks/utils/common/Android.bp
@@ -31,19 +31,12 @@
export_include_dirs: ["include"],
cflags: ["-Wthread-safety"],
static_libs: [
- "libarect",
"neuralnetworks_types",
],
shared_libs: [
- "android.hardware.neuralnetworks-V2-ndk",
"libhidlbase",
"libbinder_ndk",
],
- target: {
- android: {
- shared_libs: ["libnativewindow"],
- },
- },
}
cc_test {
@@ -51,7 +44,6 @@
host_supported: true,
srcs: ["test/*.cpp"],
static_libs: [
- "android.hardware.neuralnetworks@1.0",
"libgmock",
"libneuralnetworks_common",
"neuralnetworks_types",
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
index 2c5b648..ae0d092 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
@@ -17,8 +17,6 @@
#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
-#include <cutils/native_handle.h>
-#include <hidl/HidlSupport.h>
#include <nnapi/Result.h>
#include <nnapi/SharedMemory.h>
#include <nnapi/Types.h>
@@ -125,15 +123,6 @@
const nn::Request* request, uint32_t alignment, uint32_t padding,
std::optional<nn::Request>* maybeRequestInSharedOut, RequestRelocation* relocationOut);
-nn::GeneralResult<hidl_memory> createHidlMemoryFromSharedMemory(const nn::SharedMemory& memory);
-nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory);
-
-nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::Handle& handle);
-nn::GeneralResult<nn::Handle> sharedHandleFromNativeHandle(const native_handle_t* handle);
-
-nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
- const std::vector<nn::SyncFence>& fences);
-
} // namespace android::hardware::neuralnetworks::utils
#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
index b4fbfa7..b66fbd1 100644
--- a/neuralnetworks/utils/common/src/CommonUtils.cpp
+++ b/neuralnetworks/utils/common/src/CommonUtils.cpp
@@ -19,8 +19,6 @@
#include "HandleError.h"
#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-#include <hidl/HidlSupport.h>
#include <nnapi/Result.h>
#include <nnapi/SharedMemory.h>
#include <nnapi/TypeUtils.h>
@@ -34,11 +32,6 @@
#include <variant>
#include <vector>
-#ifdef __ANDROID__
-#include <android/hardware_buffer.h>
-#include <vndk/hardware_buffer.h>
-#endif // __ANDROID__
-
namespace android::hardware::neuralnetworks::utils {
namespace {
@@ -92,97 +85,6 @@
});
}
-nn::GeneralResult<hidl_handle> createNativeHandleFrom(std::vector<base::unique_fd> fds,
- const std::vector<int32_t>& ints) {
- constexpr size_t kIntMax = std::numeric_limits<int>::max();
- CHECK_LE(fds.size(), kIntMax);
- CHECK_LE(ints.size(), kIntMax);
- native_handle_t* nativeHandle =
- native_handle_create(static_cast<int>(fds.size()), static_cast<int>(ints.size()));
- if (nativeHandle == nullptr) {
- return NN_ERROR() << "Failed to create native_handle";
- }
-
- for (size_t i = 0; i < fds.size(); ++i) {
- nativeHandle->data[i] = fds[i].release();
- }
- std::copy(ints.begin(), ints.end(), nativeHandle->data + nativeHandle->numFds);
-
- hidl_handle handle;
- handle.setTo(nativeHandle, /*shouldOwn=*/true);
- return handle;
-}
-
-nn::GeneralResult<hidl_handle> createNativeHandleFrom(base::unique_fd fd,
- const std::vector<int32_t>& ints) {
- std::vector<base::unique_fd> fds;
- fds.push_back(std::move(fd));
- return createNativeHandleFrom(std::move(fds), ints);
-}
-
-nn::GeneralResult<hidl_handle> createNativeHandleFrom(const nn::Memory::Unknown::Handle& handle) {
- std::vector<base::unique_fd> fds = NN_TRY(nn::dupFds(handle.fds.begin(), handle.fds.end()));
- return createNativeHandleFrom(std::move(fds), handle.ints);
-}
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Ashmem& memory) {
- auto fd = NN_TRY(nn::dupFd(memory.fd));
- auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), {}));
- return hidl_memory("ashmem", std::move(handle), memory.size);
-}
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Fd& memory) {
- auto fd = NN_TRY(nn::dupFd(memory.fd));
-
- const auto [lowOffsetBits, highOffsetBits] = nn::getIntsFromOffset(memory.offset);
- const std::vector<int> ints = {memory.prot, lowOffsetBits, highOffsetBits};
-
- auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), ints));
- return hidl_memory("mmap_fd", std::move(handle), memory.size);
-}
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::HardwareBuffer& memory) {
-#ifdef __ANDROID__
- const auto* ahwb = memory.handle.get();
- AHardwareBuffer_Desc bufferDesc;
- AHardwareBuffer_describe(ahwb, &bufferDesc);
-
- const bool isBlob = bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB;
- const size_t size = isBlob ? bufferDesc.width : 0;
- const char* const name = isBlob ? "hardware_buffer_blob" : "hardware_buffer";
-
- const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
- const hidl_handle hidlHandle(nativeHandle);
- hidl_handle copiedHandle(hidlHandle);
-
- return hidl_memory(name, std::move(copiedHandle), size);
-#else // __ANDROID__
- LOG(FATAL) << "nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const "
- "nn::Memory::HardwareBuffer& memory): Not Available on Host Build";
- (void)memory;
- return (NN_ERROR() << "createHidlMemoryFrom failed").operator nn::GeneralResult<hidl_memory>();
-#endif // __ANDROID__
-}
-
-nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Unknown& memory) {
- return hidl_memory(memory.name, NN_TRY(createNativeHandleFrom(memory.handle)), memory.size);
-}
-
-nn::GeneralResult<nn::Memory::Unknown::Handle> unknownHandleFromNativeHandle(
- const native_handle_t* handle) {
- if (handle == nullptr) {
- return NN_ERROR() << "unknownHandleFromNativeHandle failed because handle is nullptr";
- }
-
- std::vector<base::unique_fd> fds =
- NN_TRY(nn::dupFds(handle->data + 0, handle->data + handle->numFds));
-
- std::vector<int> ints(handle->data + handle->numFds,
- handle->data + handle->numFds + handle->numInts);
-
- return nn::Memory::Unknown::Handle{.fds = std::move(fds), .ints = std::move(ints)};
-}
-
} // anonymous namespace
nn::Capabilities::OperandPerformanceTable makeQuantized8PerformanceConsistentWithP(
@@ -331,142 +233,4 @@
return **maybeRequestInSharedOut;
}
-nn::GeneralResult<hidl_memory> createHidlMemoryFromSharedMemory(const nn::SharedMemory& memory) {
- if (memory == nullptr) {
- return NN_ERROR() << "Memory must be non-empty";
- }
- return std::visit([](const auto& x) { return createHidlMemoryFrom(x); }, memory->handle);
-}
-
-#ifdef __ANDROID__
-static uint32_t roundUpToMultiple(uint32_t value, uint32_t multiple) {
- return (value + multiple - 1) / multiple * multiple;
-}
-#endif // __ANDROID__
-
-nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory) {
- CHECK_LE(memory.size(), std::numeric_limits<size_t>::max());
- if (!memory.valid()) {
- return NN_ERROR() << "Unable to convert invalid hidl_memory";
- }
-
- if (memory.name() == "ashmem") {
- if (memory.handle()->numFds != 1) {
- return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
- << memory.handle()->numFds << " numFds, but expected 1";
- }
- if (memory.handle()->numInts != 0) {
- return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
- << memory.handle()->numInts << " numInts, but expected 0";
- }
- auto handle = nn::Memory::Ashmem{
- .fd = NN_TRY(nn::dupFd(memory.handle()->data[0])),
- .size = static_cast<size_t>(memory.size()),
- };
- return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
- }
-
- if (memory.name() == "mmap_fd") {
- if (memory.handle()->numFds != 1) {
- return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
- << memory.handle()->numFds << " numFds, but expected 1";
- }
- if (memory.handle()->numInts != 3) {
- return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
- << memory.handle()->numInts << " numInts, but expected 3";
- }
-
- const int fd = memory.handle()->data[0];
- const int prot = memory.handle()->data[1];
- const int lower = memory.handle()->data[2];
- const int higher = memory.handle()->data[3];
- const size_t offset = nn::getOffsetFromInts(lower, higher);
-
- return nn::createSharedMemoryFromFd(static_cast<size_t>(memory.size()), prot, fd, offset);
- }
-
- if (memory.name() != "hardware_buffer_blob") {
- auto handle = nn::Memory::Unknown{
- .handle = NN_TRY(unknownHandleFromNativeHandle(memory.handle())),
- .size = static_cast<size_t>(memory.size()),
- .name = memory.name(),
- };
- return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
- }
-
-#ifdef __ANDROID__
- const auto size = memory.size();
- const auto format = AHARDWAREBUFFER_FORMAT_BLOB;
- const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
- const uint32_t width = size;
- const uint32_t height = 1; // height is always 1 for BLOB mode AHardwareBuffer.
- const uint32_t layers = 1; // layers is always 1 for BLOB mode AHardwareBuffer.
-
- // AHardwareBuffer_createFromHandle() might fail because an allocator
- // expects a specific stride value. In that case, we try to guess it by
- // aligning the width to small powers of 2.
- // TODO(b/174120849): Avoid stride assumptions.
- AHardwareBuffer* hardwareBuffer = nullptr;
- status_t status = UNKNOWN_ERROR;
- for (uint32_t alignment : {1, 4, 32, 64, 128, 2, 8, 16}) {
- const uint32_t stride = roundUpToMultiple(width, alignment);
- AHardwareBuffer_Desc desc{
- .width = width,
- .height = height,
- .layers = layers,
- .format = format,
- .usage = usage,
- .stride = stride,
- };
- status = AHardwareBuffer_createFromHandle(&desc, memory.handle(),
- AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
- &hardwareBuffer);
- if (status == NO_ERROR) {
- break;
- }
- }
- if (status != NO_ERROR) {
- return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "Can't create AHardwareBuffer from handle. Error: " << status;
- }
-
- return nn::createSharedMemoryFromAHWB(hardwareBuffer, /*takeOwnership=*/true);
-#else // __ANDROID__
- LOG(FATAL) << "nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const "
- "hidl_memory& memory): Not Available on Host Build";
- return (NN_ERROR() << "createSharedMemoryFromHidlMemory failed")
- .
- operator nn::GeneralResult<nn::SharedMemory>();
-#endif // __ANDROID__
-}
-
-nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::Handle& handle) {
- base::unique_fd fd = NN_TRY(nn::dupFd(handle.get()));
- return createNativeHandleFrom(std::move(fd), {});
-}
-
-nn::GeneralResult<nn::Handle> sharedHandleFromNativeHandle(const native_handle_t* handle) {
- if (handle == nullptr) {
- return NN_ERROR() << "sharedHandleFromNativeHandle failed because handle is nullptr";
- }
- if (handle->numFds != 1 || handle->numInts != 0) {
- return NN_ERROR() << "sharedHandleFromNativeHandle failed because handle does not only "
- "hold a single fd";
- }
- return nn::dupFd(handle->data[0]);
-}
-
-nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
- const std::vector<nn::SyncFence>& syncFences) {
- hidl_vec<hidl_handle> handles(syncFences.size());
- for (size_t i = 0; i < syncFences.size(); ++i) {
- const auto& handle = syncFences[i].getSharedHandle();
- if (handle == nullptr) {
- return NN_ERROR() << "convertSyncFences failed because sync fence is empty";
- }
- handles[i] = NN_TRY(hidlHandleFromSharedHandle(*handle));
- }
- return handles;
-}
-
} // namespace android::hardware::neuralnetworks::utils