Replace HIDL memory types with canonical Memory
Bug: 169672209
Test: NNT_static
Change-Id: Ic3d22cd283c96f0864349342b1327ee8fe29f697
Merged-In: Ic3d22cd283c96f0864349342b1327ee8fe29f697
(cherry picked from commit bb6b0a408afb14f19120bbf9977918d9d485b192)
diff --git a/runtime/Memory.cpp b/runtime/Memory.cpp
index 7efaf64..e3d2c24 100644
--- a/runtime/Memory.cpp
+++ b/runtime/Memory.cpp
@@ -21,6 +21,10 @@
#include <android-base/scopeguard.h>
#include <android/hardware_buffer.h>
#include <cutils/native_handle.h>
+#include <hidl/HidlSupport.h>
+#include <nnapi/SharedMemory.h>
+#include <nnapi/TypeUtils.h>
+#include <nnapi/Types.h>
#include <vndk/hardware_buffer.h>
#include <algorithm>
@@ -30,21 +34,15 @@
#include <utility>
#include <vector>
-#include <nnapi/TypeUtils.h>
-#include <nnapi/Types.h>
#include "CompilationBuilder.h"
#include "CpuExecutor.h"
#include "ExecutionBurstController.h"
#include "Manager.h"
-#include "MemoryUtils.h"
#include "TypeManager.h"
#include "Utils.h"
namespace android {
namespace nn {
-
-using ::android::hidl::memory::V1_0::IMemory;
-
namespace {
// The validator for a client-managed single-dimensional memory pool with a known size.
@@ -185,16 +183,14 @@
} // namespace
-RuntimeMemory::RuntimeMemory(hardware::hidl_memory memory)
- : kHidlMemory(std::move(memory)),
- mValidator(std::make_unique<SizedMemoryValidator>(kHidlMemory.size())) {}
+RuntimeMemory::RuntimeMemory(Memory memory)
+ : kMemory(std::move(memory)),
+ mValidator(std::make_unique<SizedMemoryValidator>(kMemory.size)) {}
-RuntimeMemory::RuntimeMemory(hardware::hidl_memory memory,
- std::unique_ptr<MemoryValidatorBase> validator)
- : kHidlMemory(std::move(memory)), mValidator(std::move(validator)) {}
+RuntimeMemory::RuntimeMemory(Memory memory, std::unique_ptr<MemoryValidatorBase> validator)
+ : kMemory(std::move(memory)), mValidator(std::move(validator)) {}
-RuntimeMemory::RuntimeMemory(sp<V1_3::IBuffer> buffer, uint32_t token)
- : kBuffer(std::move(buffer)), kToken(token) {}
+RuntimeMemory::RuntimeMemory(SharedBuffer buffer) : kBuffer(std::move(buffer)) {}
RuntimeMemory::~RuntimeMemory() {
for (const auto& [ptr, weakBurst] : mUsedBy) {
@@ -204,20 +200,17 @@
}
}
-V1_3::Request::MemoryPool RuntimeMemory::getMemoryPool() const {
- V1_3::Request::MemoryPool pool;
- if (kToken > 0) {
- pool.token(kToken);
- } else {
- pool.hidlMemory(kHidlMemory);
+Request::MemoryPool RuntimeMemory::getMemoryPool() const {
+ if (kBuffer != nullptr) {
+ return kBuffer->getToken();
}
- return pool;
+ return kMemory;
}
std::optional<RunTimePoolInfo> RuntimeMemory::getRunTimePoolInfo() const {
std::lock_guard<std::mutex> guard(mMutex);
if (!mHasCachedRunTimePoolInfo) {
- mCachedRunTimePoolInfo = RunTimePoolInfo::createFromMemory(uncheckedConvert(kHidlMemory));
+ mCachedRunTimePoolInfo = RunTimePoolInfo::createFromMemory(kMemory);
mHasCachedRunTimePoolInfo = true;
}
return mCachedRunTimePoolInfo;
@@ -249,33 +242,33 @@
return ANEURALNETWORKS_NO_ERROR;
}
-int copyIBufferToHidlMemory(const sp<V1_3::IBuffer>& src, const hardware::hidl_memory& dst) {
+int copyIBufferToMemory(const SharedBuffer& src, const Memory& dst) {
const auto ret = src->copyTo(dst);
- if (!ret.isOk()) {
- LOG(ERROR) << "ANeuralNetworksMemory_copy failure: " << ret.description();
- return ANEURALNETWORKS_OP_FAILED;
+ if (!ret.has_value()) {
+ LOG(ERROR) << "ANeuralNetworksMemory_copy failure: " << ret.error().message;
+ return convertErrorStatusToResultCode(ret.error().code);
}
- return convertErrorStatusToResultCode(static_cast<V1_3::ErrorStatus>(ret));
+ return ANEURALNETWORKS_NO_ERROR;
}
-int copyHidlMemoryToIBuffer(const hardware::hidl_memory& src, const sp<V1_3::IBuffer>& dst,
- const std::vector<uint32_t>& dimensions) {
+int copyMemoryToIBuffer(const Memory& src, const SharedBuffer& dst,
+ const std::vector<uint32_t>& dimensions) {
const auto ret = dst->copyFrom(src, dimensions);
- if (!ret.isOk()) {
- LOG(ERROR) << "ANeuralNetworksMemory_copy failure: " << ret.description();
- return ANEURALNETWORKS_OP_FAILED;
+ if (!ret.has_value()) {
+ LOG(ERROR) << "ANeuralNetworksMemory_copy failure: " << ret.error().message;
+ return convertErrorStatusToResultCode(ret.error().code);
}
- return convertErrorStatusToResultCode(static_cast<V1_3::ErrorStatus>(ret));
+ return ANEURALNETWORKS_NO_ERROR;
}
-static int copyIBuffers(const sp<V1_3::IBuffer>& src, const sp<V1_3::IBuffer>& dst,
+static int copyIBuffers(const SharedBuffer& src, const SharedBuffer& dst,
const MemoryValidatorBase::Metadata& srcMetadata) {
- const auto [n, memory] = MemoryRuntimeAHWB::create(srcMetadata.logicalSize);
+ const auto [n, memoryAHWB] = MemoryRuntimeAHWB::create(srcMetadata.logicalSize);
NN_RETURN_IF_ERROR(n);
- const hardware::hidl_memory& hidlMemory = memory->getHidlMemory();
- if (!hidlMemory.valid()) return ANEURALNETWORKS_OUT_OF_MEMORY;
- NN_RETURN_IF_ERROR(copyIBufferToHidlMemory(src, hidlMemory));
- NN_RETURN_IF_ERROR(copyHidlMemoryToIBuffer(hidlMemory, dst, srcMetadata.dimensions));
+ const Memory& memory = memoryAHWB->getMemory();
+ if (!validate(memory).ok()) return ANEURALNETWORKS_OUT_OF_MEMORY;
+ NN_RETURN_IF_ERROR(copyIBufferToMemory(src, memory));
+ NN_RETURN_IF_ERROR(copyMemoryToIBuffer(memory, dst, srcMetadata.dimensions));
return ANEURALNETWORKS_NO_ERROR;
}
@@ -293,19 +286,18 @@
return ANEURALNETWORKS_BAD_DATA;
}
- bool srcHasHidlMemory = src.getHidlMemory().valid();
- bool dstHasHidlMemory = dst.getHidlMemory().valid();
+ bool srcHasMemory = validate(src.getMemory()).ok();
+ bool dstHasMemory = validate(dst.getMemory()).ok();
bool srcHasIBuffer = src.getIBuffer() != nullptr;
bool dstHasIBuffer = dst.getIBuffer() != nullptr;
if (srcHasIBuffer && dstHasIBuffer) {
return copyIBuffers(src.getIBuffer(), dst.getIBuffer(), srcMetadata);
- } else if (srcHasHidlMemory && dstHasHidlMemory) {
+ } else if (srcHasMemory && dstHasMemory) {
return copyHidlMemories(src.getRunTimePoolInfo(), dst.getRunTimePoolInfo());
- } else if (srcHasHidlMemory && dstHasIBuffer) {
- return copyHidlMemoryToIBuffer(src.getHidlMemory(), dst.getIBuffer(),
- srcMetadata.dimensions);
- } else if (srcHasIBuffer && dstHasHidlMemory) {
- return copyIBufferToHidlMemory(src.getIBuffer(), dst.getHidlMemory());
+ } else if (srcHasMemory && dstHasIBuffer) {
+ return copyMemoryToIBuffer(src.getMemory(), dst.getIBuffer(), srcMetadata.dimensions);
+ } else if (srcHasIBuffer && dstHasMemory) {
+ return copyIBufferToMemory(src.getIBuffer(), dst.getMemory());
}
return ANEURALNETWORKS_OP_FAILED;
}
@@ -524,86 +516,56 @@
}
std::pair<int, std::unique_ptr<MemoryAshmem>> MemoryAshmem::create(uint32_t size) {
- hardware::hidl_memory hidlMemory = allocateSharedMemory(size);
- sp<IMemory> mapped = mapMemory(hidlMemory);
- if (mapped == nullptr || mapped->getPointer() == nullptr) {
- LOG(ERROR) << "RuntimeMemory::create failed";
- return {ANEURALNETWORKS_OUT_OF_MEMORY, nullptr};
+ auto memory = createSharedMemory(size);
+ if (!memory.has_value()) {
+ LOG(ERROR) << "RuntimeMemory::create() failed: " << memory.error().message;
+ return {convertErrorStatusToResultCode(memory.error().code), nullptr};
+ }
+ auto mapping = map(memory.value());
+ if (!mapping.has_value()) {
+ LOG(ERROR) << "RuntimeMemory::create() map failed: " << mapping.error().message;
+ return {convertErrorStatusToResultCode(mapping.error().code), nullptr};
}
return {ANEURALNETWORKS_NO_ERROR,
- std::make_unique<MemoryAshmem>(std::move(mapped), std::move(hidlMemory))};
+ std::make_unique<MemoryAshmem>(std::move(memory).value(), std::move(mapping).value())};
}
uint8_t* MemoryAshmem::getPointer() const {
- return static_cast<uint8_t*>(static_cast<void*>(kMappedMemory->getPointer()));
+ return static_cast<uint8_t*>(std::get<void*>(kMapping.pointer));
}
-MemoryAshmem::MemoryAshmem(sp<IMemory> mapped, hardware::hidl_memory memory)
- : RuntimeMemory(std::move(memory)), kMappedMemory(std::move(mapped)) {}
+MemoryAshmem::MemoryAshmem(Memory memory, Mapping mapping)
+ : RuntimeMemory(std::move(memory)), kMapping(std::move(mapping)) {}
std::pair<int, std::unique_ptr<MemoryFd>> MemoryFd::create(size_t size, int prot, int fd,
size_t offset) {
- if (size == 0 || fd < 0) {
- LOG(ERROR) << "Invalid size or fd";
- return {ANEURALNETWORKS_BAD_DATA, nullptr};
+ auto memory = createSharedMemoryFromFd(size, prot, fd, offset);
+ if (!memory.has_value()) {
+ LOG(ERROR) << "Failed to create memory from fd: " << memory.error().message;
+ return {convertErrorStatusToResultCode(memory.error().code), nullptr};
}
-
- // Duplicate the file descriptor so MemoryFd owns its own version.
- int dupfd = dup(fd);
- if (dupfd == -1) {
- LOG(ERROR) << "Failed to dup the fd";
- // TODO(b/120417090): is ANEURALNETWORKS_UNEXPECTED_NULL the correct
- // error to return here?
- return {ANEURALNETWORKS_UNEXPECTED_NULL, nullptr};
- }
-
- // Create a temporary native handle to own the dupfd.
- native_handle_t* nativeHandle = native_handle_create(1, 3);
- if (nativeHandle == nullptr) {
- LOG(ERROR) << "Failed to create native_handle";
- close(dupfd);
- // TODO(b/120417090): is ANEURALNETWORKS_UNEXPECTED_NULL the correct
- // error to return here?
- return {ANEURALNETWORKS_UNEXPECTED_NULL, nullptr};
- }
- nativeHandle->data[0] = dupfd;
- nativeHandle->data[1] = prot;
- const uint64_t bits = static_cast<uint64_t>(offset);
- nativeHandle->data[2] = (int32_t)(uint32_t)(bits & 0xffffffff);
- nativeHandle->data[3] = (int32_t)(uint32_t)(bits >> 32);
-
- // Create a hidl_handle which owns the native handle and fd so that we don't
- // have to manually clean either the native handle or the fd.
- hardware::hidl_handle hidlHandle;
- hidlHandle.setTo(nativeHandle, /*shouldOwn=*/true);
-
- // Push the hidl_handle into a hidl_memory object. The hidl_memory object is
- // responsible for cleaning the hidl_handle, the native handle, and the fd.
- hardware::hidl_memory hidlMemory =
- hardware::hidl_memory("mmap_fd", std::move(hidlHandle), size);
-
- return {ANEURALNETWORKS_NO_ERROR, std::make_unique<MemoryFd>(std::move(hidlMemory))};
+ return {ANEURALNETWORKS_NO_ERROR, std::make_unique<MemoryFd>(std::move(memory).value())};
}
-MemoryFd::MemoryFd(hardware::hidl_memory memory) : RuntimeMemory(std::move(memory)) {}
+MemoryFd::MemoryFd(Memory memory) : RuntimeMemory(std::move(memory)) {}
std::pair<int, std::unique_ptr<MemoryAHWB>> MemoryAHWB::create(const AHardwareBuffer& ahwb) {
- AHardwareBuffer_Desc bufferDesc;
- AHardwareBuffer_describe(&ahwb, &bufferDesc);
- const native_handle_t* handle = AHardwareBuffer_getNativeHandle(&ahwb);
- hardware::hidl_memory hidlMemory;
+ auto memory = createSharedMemoryFromAHWB(ahwb);
+ if (!memory.has_value()) {
+ LOG(ERROR) << "Failed to create memory from AHWB: " << memory.error().message;
+ return {convertErrorStatusToResultCode(memory.error().code), nullptr};
+ }
+
std::unique_ptr<MemoryValidatorBase> validator;
- if (bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
- hidlMemory = hardware::hidl_memory("hardware_buffer_blob", handle, bufferDesc.width);
- validator = std::make_unique<SizedMemoryValidator>(bufferDesc.width);
+ if (memory.value().name == "hardware_buffer_blob") {
+ validator = std::make_unique<SizedMemoryValidator>(memory.value().size);
} else {
- // memory size is not used.
- hidlMemory = hardware::hidl_memory("hardware_buffer", handle, 0);
validator = std::make_unique<AHardwareBufferNonBlobValidator>();
}
- auto memory = std::make_unique<MemoryAHWB>(std::move(hidlMemory), std::move(validator));
- return {ANEURALNETWORKS_NO_ERROR, std::move(memory)};
-};
+
+ auto memoryAHWB = std::make_unique<MemoryAHWB>(std::move(memory).value(), std::move(validator));
+ return {ANEURALNETWORKS_NO_ERROR, std::move(memoryAHWB)};
+}
std::pair<int, std::unique_ptr<MemoryRuntimeAHWB>> MemoryRuntimeAHWB::create(uint32_t size) {
AHardwareBuffer* ahwb = nullptr;
@@ -621,58 +583,43 @@
LOG(ERROR) << "Failed to allocate BLOB mode AHWB.";
return {ANEURALNETWORKS_OP_FAILED, nullptr};
}
- auto allocateGuard = base::make_scope_guard([&ahwb]() { AHardwareBuffer_release(ahwb); });
+ auto ahwbGuard = base::make_scope_guard([ahwb]() { AHardwareBuffer_release(ahwb); });
- void* buffer = nullptr;
- err = AHardwareBuffer_lock(ahwb, usage, -1, nullptr, &buffer);
- if (err != 0 || buffer == nullptr) {
- LOG(ERROR) << "Failed to lock BLOB mode AHWB.";
- return {ANEURALNETWORKS_OP_FAILED, nullptr};
+ auto memory = createSharedMemoryFromAHWB(*ahwb);
+ if (!memory.has_value()) {
+ LOG(ERROR) << "Failed to allocate BLOB mode AHWB: " << memory.error().message;
+ return {convertErrorStatusToResultCode(memory.error().code), nullptr};
}
- auto lockGuard = base::make_scope_guard([&ahwb]() { AHardwareBuffer_unlock(ahwb, nullptr); });
-
- const native_handle_t* handle = AHardwareBuffer_getNativeHandle(ahwb);
- if (handle == nullptr) {
- LOG(ERROR) << "Failed to retrieve the native handle from the AHWB.";
- return {ANEURALNETWORKS_OP_FAILED, nullptr};
+ auto mapping = map(memory.value());
+ if (!mapping.has_value()) {
+ LOG(ERROR) << "Failed to map BLOB mode AHWB: " << mapping.error().message;
+ return {convertErrorStatusToResultCode(mapping.error().code), nullptr};
}
-
- hardware::hidl_memory hidlMemory =
- hardware::hidl_memory("hardware_buffer_blob", handle, desc.width);
- auto memory = std::make_unique<MemoryRuntimeAHWB>(std::move(hidlMemory), ahwb,
- static_cast<uint8_t*>(buffer));
- allocateGuard.Disable();
- lockGuard.Disable();
- return {ANEURALNETWORKS_NO_ERROR, std::move(memory)};
+ auto memoryAHWB = std::make_unique<MemoryRuntimeAHWB>(
+ std::move(memory).value(), std::move(ahwbGuard), std::move(mapping).value());
+ return {ANEURALNETWORKS_NO_ERROR, std::move(memoryAHWB)};
}
-MemoryRuntimeAHWB::MemoryRuntimeAHWB(hardware::hidl_memory memory, AHardwareBuffer* ahwb,
- uint8_t* buffer)
- : RuntimeMemory(std::move(memory)), mAhwb(ahwb), mBuffer(buffer) {
- CHECK(mAhwb != nullptr);
- CHECK(mBuffer != nullptr);
+uint8_t* MemoryRuntimeAHWB::getPointer() const {
+ return static_cast<uint8_t*>(std::get<void*>(kMapping.pointer));
}
-MemoryRuntimeAHWB::~MemoryRuntimeAHWB() {
- AHardwareBuffer_unlock(mAhwb, nullptr);
- AHardwareBuffer_release(mAhwb);
-}
+MemoryRuntimeAHWB::MemoryRuntimeAHWB(Memory memory,
+ base::ScopeGuard<std::function<void()>> ahwbScopeGuard,
+ Mapping mapping)
+ : RuntimeMemory(std::move(memory)),
+ kAhwbScopeGuard(std::move(ahwbScopeGuard)),
+ kMapping(std::move(mapping)) {}
-std::pair<int, std::unique_ptr<MemoryFromDevice>> MemoryFromDevice::create(sp<V1_3::IBuffer> buffer,
- uint32_t token) {
+std::pair<int, std::unique_ptr<MemoryFromDevice>> MemoryFromDevice::create(SharedBuffer buffer) {
if (buffer == nullptr) {
LOG(ERROR) << "nullptr IBuffer for device memory.";
return {ANEURALNETWORKS_OP_FAILED, nullptr};
}
- if (token <= 0) {
- LOG(ERROR) << "Invalid token for device memory: " << token;
- return {ANEURALNETWORKS_OP_FAILED, nullptr};
- }
- return {ANEURALNETWORKS_NO_ERROR, std::make_unique<MemoryFromDevice>(std::move(buffer), token)};
-};
+ return {ANEURALNETWORKS_NO_ERROR, std::make_unique<MemoryFromDevice>(std::move(buffer))};
+}
-MemoryFromDevice::MemoryFromDevice(sp<V1_3::IBuffer> buffer, uint32_t token)
- : RuntimeMemory(std::move(buffer), token) {}
+MemoryFromDevice::MemoryFromDevice(SharedBuffer buffer) : RuntimeMemory(std::move(buffer)) {}
} // namespace nn
} // namespace android