mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 05:49:27 +00:00
Merge changes from topic "nnapi-canonical-ahwb"
* changes: Store AHWB in NN canonical memory type -- hal Change NNAPI Memory to ref-counted SharedMemory -- hal
This commit is contained in:
@@ -41,7 +41,7 @@ class Burst final : public nn::IBurst {
|
||||
|
||||
Burst(PrivateConstructorTag tag, nn::SharedPreparedModel preparedModel);
|
||||
|
||||
OptionalCacheHold cacheMemory(const nn::Memory& memory) const override;
|
||||
OptionalCacheHold cacheMemory(const nn::SharedMemory& memory) const override;
|
||||
|
||||
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
|
||||
const nn::Request& request, nn::MeasureTiming measure) const override;
|
||||
|
||||
@@ -36,7 +36,7 @@ GeneralResult<Operand> unvalidatedConvert(const hal::V1_0::Operand& operand);
|
||||
GeneralResult<Operation> unvalidatedConvert(const hal::V1_0::Operation& operation);
|
||||
GeneralResult<Model::OperandValues> unvalidatedConvert(
|
||||
const hardware::hidl_vec<uint8_t>& operandValues);
|
||||
GeneralResult<Memory> unvalidatedConvert(const hardware::hidl_memory& memory);
|
||||
GeneralResult<SharedMemory> unvalidatedConvert(const hardware::hidl_memory& memory);
|
||||
GeneralResult<Model> unvalidatedConvert(const hal::V1_0::Model& model);
|
||||
GeneralResult<Request::Argument> unvalidatedConvert(
|
||||
const hal::V1_0::RequestArgument& requestArgument);
|
||||
@@ -65,7 +65,7 @@ nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand);
|
||||
nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation);
|
||||
nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
|
||||
const nn::Model::OperandValues& operandValues);
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory);
|
||||
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);
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Request::MemoryPool& memoryPool);
|
||||
|
||||
@@ -43,7 +43,7 @@ Burst::Burst(PrivateConstructorTag /*tag*/, nn::SharedPreparedModel preparedMode
|
||||
CHECK(kPreparedModel != nullptr);
|
||||
}
|
||||
|
||||
Burst::OptionalCacheHold Burst::cacheMemory(const nn::Memory& /*memory*/) const {
|
||||
Burst::OptionalCacheHold Burst::cacheMemory(const nn::SharedMemory& /*memory*/) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,8 +153,8 @@ GeneralResult<Model::OperandValues> unvalidatedConvert(const hidl_vec<uint8_t>&
|
||||
return Model::OperandValues(operandValues.data(), operandValues.size());
|
||||
}
|
||||
|
||||
GeneralResult<Memory> unvalidatedConvert(const hidl_memory& memory) {
|
||||
return createSharedMemoryFromHidlMemory(memory);
|
||||
GeneralResult<SharedMemory> unvalidatedConvert(const hidl_memory& memory) {
|
||||
return hal::utils::createSharedMemoryFromHidlMemory(memory);
|
||||
}
|
||||
|
||||
GeneralResult<Model> unvalidatedConvert(const hal::V1_0::Model& model) {
|
||||
@@ -346,9 +346,8 @@ nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
|
||||
return hidl_vec<uint8_t>(operandValues.data(), operandValues.data() + operandValues.size());
|
||||
}
|
||||
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory) {
|
||||
return hidl_memory(memory.name, NN_TRY(hal::utils::hidlHandleFromSharedHandle(memory.handle)),
|
||||
memory.size);
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
|
||||
return hal::utils::createHidlMemoryFromSharedMemory(memory);
|
||||
}
|
||||
|
||||
nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
|
||||
@@ -392,7 +391,7 @@ nn::GeneralResult<RequestArgument> unvalidatedConvert(
|
||||
}
|
||||
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Request::MemoryPool& memoryPool) {
|
||||
return unvalidatedConvert(std::get<nn::Memory>(memoryPool));
|
||||
return unvalidatedConvert(std::get<nn::SharedMemory>(memoryPool));
|
||||
}
|
||||
|
||||
nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request) {
|
||||
|
||||
@@ -175,7 +175,7 @@ nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
|
||||
return V1_0::utils::unvalidatedConvert(operandValues);
|
||||
}
|
||||
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory) {
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
|
||||
return V1_0::utils::unvalidatedConvert(memory);
|
||||
}
|
||||
|
||||
|
||||
@@ -304,7 +304,11 @@ GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
|
||||
}
|
||||
|
||||
GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) {
|
||||
return hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle());
|
||||
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) {
|
||||
@@ -365,7 +369,7 @@ nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
|
||||
return V1_0::utils::unvalidatedConvert(operandValues);
|
||||
}
|
||||
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory) {
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
|
||||
return V1_0::utils::unvalidatedConvert(memory);
|
||||
}
|
||||
|
||||
@@ -588,7 +592,10 @@ nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
|
||||
}
|
||||
|
||||
nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
|
||||
return hal::utils::hidlHandleFromSharedHandle(handle);
|
||||
if (handle == nullptr) {
|
||||
return {};
|
||||
}
|
||||
return hal::utils::hidlHandleFromSharedHandle(*handle);
|
||||
}
|
||||
|
||||
nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
|
||||
|
||||
@@ -42,8 +42,8 @@ class Buffer final : public nn::IBuffer {
|
||||
|
||||
nn::Request::MemoryDomainToken getToken() const override;
|
||||
|
||||
nn::GeneralResult<void> copyTo(const nn::Memory& dst) const override;
|
||||
nn::GeneralResult<void> copyFrom(const nn::Memory& src,
|
||||
nn::GeneralResult<void> copyTo(const nn::SharedMemory& dst) const override;
|
||||
nn::GeneralResult<void> copyFrom(const nn::SharedMemory& src,
|
||||
const nn::Dimensions& dimensions) const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -59,7 +59,7 @@ GeneralResult<OptionalDuration> convert(
|
||||
GeneralResult<ErrorStatus> convert(const hal::V1_3::ErrorStatus& errorStatus);
|
||||
|
||||
GeneralResult<SharedHandle> convert(const hardware::hidl_handle& handle);
|
||||
GeneralResult<Memory> convert(const hardware::hidl_memory& memory);
|
||||
GeneralResult<SharedMemory> convert(const hardware::hidl_memory& memory);
|
||||
GeneralResult<std::vector<BufferRole>> convert(
|
||||
const hardware::hidl_vec<hal::V1_3::BufferRole>& bufferRoles);
|
||||
|
||||
@@ -100,7 +100,7 @@ nn::GeneralResult<OptionalTimeoutDuration> convert(
|
||||
nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus);
|
||||
|
||||
nn::GeneralResult<hidl_handle> convert(const nn::SharedHandle& handle);
|
||||
nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory);
|
||||
nn::GeneralResult<hidl_memory> convert(const nn::SharedMemory& memory);
|
||||
nn::GeneralResult<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles);
|
||||
|
||||
nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus);
|
||||
|
||||
@@ -61,7 +61,7 @@ nn::Request::MemoryDomainToken Buffer::getToken() const {
|
||||
return kToken;
|
||||
}
|
||||
|
||||
nn::GeneralResult<void> Buffer::copyTo(const nn::Memory& dst) const {
|
||||
nn::GeneralResult<void> Buffer::copyTo(const nn::SharedMemory& dst) const {
|
||||
const auto hidlDst = NN_TRY(convert(dst));
|
||||
|
||||
const auto ret = kBuffer->copyTo(hidlDst);
|
||||
@@ -71,7 +71,7 @@ nn::GeneralResult<void> Buffer::copyTo(const nn::Memory& dst) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
nn::GeneralResult<void> Buffer::copyFrom(const nn::Memory& src,
|
||||
nn::GeneralResult<void> Buffer::copyFrom(const nn::SharedMemory& src,
|
||||
const nn::Dimensions& dimensions) const {
|
||||
const auto hidlSrc = NN_TRY(convert(src));
|
||||
const auto hidlDimensions = hidl_vec<uint32_t>(dimensions);
|
||||
|
||||
@@ -261,7 +261,7 @@ GeneralResult<Request::MemoryPool> unvalidatedConvert(
|
||||
using Discriminator = hal::V1_3::Request::MemoryPool::hidl_discriminator;
|
||||
switch (memoryPool.getDiscriminator()) {
|
||||
case Discriminator::hidlMemory:
|
||||
return createSharedMemoryFromHidlMemory(memoryPool.hidlMemory());
|
||||
return hal::utils::createSharedMemoryFromHidlMemory(memoryPool.hidlMemory());
|
||||
case Discriminator::token:
|
||||
return static_cast<Request::MemoryDomainToken>(memoryPool.token());
|
||||
}
|
||||
@@ -352,7 +352,7 @@ GeneralResult<SharedHandle> convert(const hardware::hidl_handle& handle) {
|
||||
return validatedConvert(handle);
|
||||
}
|
||||
|
||||
GeneralResult<Memory> convert(const hardware::hidl_memory& memory) {
|
||||
GeneralResult<SharedMemory> convert(const hardware::hidl_memory& memory) {
|
||||
return validatedConvert(memory);
|
||||
}
|
||||
|
||||
@@ -386,7 +386,7 @@ nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle
|
||||
return V1_2::utils::unvalidatedConvert(handle);
|
||||
}
|
||||
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory) {
|
||||
nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
|
||||
return V1_0::utils::unvalidatedConvert(memory);
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
|
||||
return unvalidatedConvertVec(arguments);
|
||||
}
|
||||
|
||||
nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Memory& memory) {
|
||||
nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::SharedMemory& memory) {
|
||||
Request::MemoryPool ret;
|
||||
ret.hidlMemory(NN_TRY(unvalidatedConvert(memory)));
|
||||
return ret;
|
||||
@@ -677,7 +677,7 @@ nn::GeneralResult<hidl_handle> convert(const nn::SharedHandle& handle) {
|
||||
return validatedConvert(handle);
|
||||
}
|
||||
|
||||
nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory) {
|
||||
nn::GeneralResult<hidl_memory> convert(const nn::SharedMemory& memory) {
|
||||
return validatedConvert(memory);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,14 @@ cc_library_static {
|
||||
local_include_dirs: ["include/nnapi/hal/aidl/"],
|
||||
export_include_dirs: ["include"],
|
||||
static_libs: [
|
||||
"libarect",
|
||||
"neuralnetworks_types",
|
||||
"neuralnetworks_utils_hal_common",
|
||||
],
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"android.hardware.neuralnetworks-V1-ndk_platform",
|
||||
"libbinder_ndk",
|
||||
"libhidlbase",
|
||||
"libnativewindow",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ GeneralResult<Model::OperandValues> unvalidatedConvert(const std::vector<uint8_t
|
||||
GeneralResult<Model::Subgraph> unvalidatedConvert(const aidl_hal::Subgraph& subgraph);
|
||||
GeneralResult<OutputShape> unvalidatedConvert(const aidl_hal::OutputShape& outputShape);
|
||||
GeneralResult<MeasureTiming> unvalidatedConvert(bool measureTiming);
|
||||
GeneralResult<Memory> unvalidatedConvert(const aidl_hal::Memory& memory);
|
||||
GeneralResult<SharedMemory> unvalidatedConvert(const aidl_hal::Memory& memory);
|
||||
GeneralResult<Timing> unvalidatedConvert(const aidl_hal::Timing& timing);
|
||||
GeneralResult<BufferDesc> unvalidatedConvert(const aidl_hal::BufferDesc& bufferDesc);
|
||||
GeneralResult<BufferRole> unvalidatedConvert(const aidl_hal::BufferRole& bufferRole);
|
||||
@@ -99,7 +99,7 @@ GeneralResult<SharedHandle> unvalidatedConvert(
|
||||
|
||||
GeneralResult<ExecutionPreference> convert(
|
||||
const aidl_hal::ExecutionPreference& executionPreference);
|
||||
GeneralResult<Memory> convert(const aidl_hal::Memory& memory);
|
||||
GeneralResult<SharedMemory> convert(const aidl_hal::Memory& memory);
|
||||
GeneralResult<Model> convert(const aidl_hal::Model& model);
|
||||
GeneralResult<Operand> convert(const aidl_hal::Operand& operand);
|
||||
GeneralResult<OperandType> convert(const aidl_hal::OperandType& operandType);
|
||||
@@ -108,7 +108,7 @@ GeneralResult<Request::MemoryPool> convert(const aidl_hal::RequestMemoryPool& me
|
||||
GeneralResult<Request> convert(const aidl_hal::Request& request);
|
||||
|
||||
GeneralResult<std::vector<Operation>> convert(const std::vector<aidl_hal::Operation>& outputShapes);
|
||||
GeneralResult<std::vector<Memory>> convert(const std::vector<aidl_hal::Memory>& memories);
|
||||
GeneralResult<std::vector<SharedMemory>> convert(const std::vector<aidl_hal::Memory>& memories);
|
||||
|
||||
GeneralResult<std::vector<uint32_t>> toUnsigned(const std::vector<int32_t>& vec);
|
||||
|
||||
@@ -118,11 +118,11 @@ namespace aidl::android::hardware::neuralnetworks::utils {
|
||||
|
||||
namespace nn = ::android::nn;
|
||||
|
||||
nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory& memory);
|
||||
nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory);
|
||||
nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape);
|
||||
nn::GeneralResult<ErrorStatus> unvalidatedConvert(const nn::ErrorStatus& errorStatus);
|
||||
|
||||
nn::GeneralResult<Memory> convert(const nn::Memory& memory);
|
||||
nn::GeneralResult<Memory> convert(const nn::SharedMemory& memory);
|
||||
nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus);
|
||||
nn::GeneralResult<std::vector<OutputShape>> convert(
|
||||
const std::vector<nn::OutputShape>& outputShapes);
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#include <aidl/android/hardware/common/NativeHandle.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android/hardware_buffer.h>
|
||||
#include <cutils/native_handle.h>
|
||||
#include <nnapi/OperandTypes.h>
|
||||
#include <nnapi/OperationTypes.h>
|
||||
#include <nnapi/Result.h>
|
||||
@@ -27,6 +29,7 @@
|
||||
#include <nnapi/Validation.h>
|
||||
#include <nnapi/hal/CommonUtils.h>
|
||||
#include <nnapi/hal/HandleError.h>
|
||||
#include <vndk/hardware_buffer.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -53,6 +56,8 @@ constexpr auto kVersion = android::nn::Version::ANDROID_S;
|
||||
namespace android::nn {
|
||||
namespace {
|
||||
|
||||
using ::aidl::android::hardware::common::NativeHandle;
|
||||
|
||||
constexpr auto validOperandType(nn::OperandType operandType) {
|
||||
switch (operandType) {
|
||||
case nn::OperandType::FLOAT32:
|
||||
@@ -125,6 +130,61 @@ GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
|
||||
return canonical;
|
||||
}
|
||||
|
||||
GeneralResult<Handle> unvalidatedConvertHelper(const NativeHandle& aidlNativeHandle) {
|
||||
std::vector<base::unique_fd> fds;
|
||||
fds.reserve(aidlNativeHandle.fds.size());
|
||||
for (const auto& fd : aidlNativeHandle.fds) {
|
||||
const int dupFd = dup(fd.get());
|
||||
if (dupFd == -1) {
|
||||
// TODO(b/120417090): is ANEURALNETWORKS_UNEXPECTED_NULL the correct error to return
|
||||
// here?
|
||||
return NN_ERROR() << "Failed to dup the fd";
|
||||
}
|
||||
fds.emplace_back(dupFd);
|
||||
}
|
||||
|
||||
return Handle{.fds = std::move(fds), .ints = aidlNativeHandle.ints};
|
||||
}
|
||||
|
||||
struct NativeHandleDeleter {
|
||||
void operator()(native_handle_t* handle) const {
|
||||
if (handle) {
|
||||
native_handle_close(handle);
|
||||
native_handle_delete(handle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using UniqueNativeHandle = std::unique_ptr<native_handle_t, NativeHandleDeleter>;
|
||||
|
||||
static nn::GeneralResult<UniqueNativeHandle> nativeHandleFromAidlHandle(
|
||||
const NativeHandle& handle) {
|
||||
std::vector<base::unique_fd> fds;
|
||||
fds.reserve(handle.fds.size());
|
||||
for (const auto& fd : handle.fds) {
|
||||
const int dupFd = dup(fd.get());
|
||||
if (dupFd == -1) {
|
||||
return NN_ERROR() << "Failed to dup the fd";
|
||||
}
|
||||
fds.emplace_back(dupFd);
|
||||
}
|
||||
|
||||
constexpr size_t kIntMax = std::numeric_limits<int>::max();
|
||||
CHECK_LE(handle.fds.size(), kIntMax);
|
||||
CHECK_LE(handle.ints.size(), kIntMax);
|
||||
native_handle_t* nativeHandle = native_handle_create(static_cast<int>(handle.fds.size()),
|
||||
static_cast<int>(handle.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(handle.ints.begin(), handle.ints.end(), &nativeHandle->data[nativeHandle->numFds]);
|
||||
|
||||
return UniqueNativeHandle(nativeHandle);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
GeneralResult<OperandType> unvalidatedConvert(const aidl_hal::OperandType& operandType) {
|
||||
@@ -316,13 +376,67 @@ GeneralResult<MeasureTiming> unvalidatedConvert(bool measureTiming) {
|
||||
return measureTiming ? MeasureTiming::YES : MeasureTiming::NO;
|
||||
}
|
||||
|
||||
GeneralResult<Memory> unvalidatedConvert(const aidl_hal::Memory& memory) {
|
||||
static uint32_t roundUpToMultiple(uint32_t value, uint32_t multiple) {
|
||||
return (value + multiple - 1) / multiple * multiple;
|
||||
}
|
||||
|
||||
GeneralResult<SharedMemory> unvalidatedConvert(const aidl_hal::Memory& memory) {
|
||||
VERIFY_NON_NEGATIVE(memory.size) << "Memory size must not be negative";
|
||||
return Memory{
|
||||
.handle = NN_TRY(unvalidatedConvert(memory.handle)),
|
||||
if (memory.size > std::numeric_limits<uint32_t>::max()) {
|
||||
return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
|
||||
}
|
||||
|
||||
if (memory.name != "hardware_buffer_blob") {
|
||||
return std::make_shared<const Memory>(Memory{
|
||||
.handle = NN_TRY(unvalidatedConvertHelper(memory.handle)),
|
||||
.size = static_cast<uint32_t>(memory.size),
|
||||
.name = memory.name,
|
||||
});
|
||||
}
|
||||
|
||||
const auto size = static_cast<uint32_t>(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.
|
||||
|
||||
const UniqueNativeHandle handle = NN_TRY(nativeHandleFromAidlHandle(memory.handle));
|
||||
const native_handle_t* nativeHandle = handle.get();
|
||||
|
||||
// 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, nativeHandle,
|
||||
AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
|
||||
&hardwareBuffer);
|
||||
if (status == NO_ERROR) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (status != NO_ERROR) {
|
||||
return NN_ERROR(ErrorStatus::GENERAL_FAILURE)
|
||||
<< "Can't create AHardwareBuffer from handle. Error: " << status;
|
||||
}
|
||||
|
||||
return std::make_shared<const Memory>(Memory{
|
||||
.handle = HardwareBufferHandle(hardwareBuffer, /*takeOwnership=*/true),
|
||||
.size = static_cast<uint32_t>(memory.size),
|
||||
.name = memory.name,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
GeneralResult<Model::OperandValues> unvalidatedConvert(const std::vector<uint8_t>& operandValues) {
|
||||
@@ -397,24 +511,8 @@ GeneralResult<ExecutionPreference> unvalidatedConvert(
|
||||
return static_cast<ExecutionPreference>(executionPreference);
|
||||
}
|
||||
|
||||
GeneralResult<SharedHandle> unvalidatedConvert(
|
||||
const ::aidl::android::hardware::common::NativeHandle& aidlNativeHandle) {
|
||||
std::vector<base::unique_fd> fds;
|
||||
fds.reserve(aidlNativeHandle.fds.size());
|
||||
for (const auto& fd : aidlNativeHandle.fds) {
|
||||
int dupFd = dup(fd.get());
|
||||
if (dupFd == -1) {
|
||||
// TODO(b/120417090): is ANEURALNETWORKS_UNEXPECTED_NULL the correct error to return
|
||||
// here?
|
||||
return NN_ERROR() << "Failed to dup the fd";
|
||||
}
|
||||
fds.emplace_back(dupFd);
|
||||
}
|
||||
|
||||
return std::make_shared<const Handle>(Handle{
|
||||
.fds = std::move(fds),
|
||||
.ints = aidlNativeHandle.ints,
|
||||
});
|
||||
GeneralResult<SharedHandle> unvalidatedConvert(const NativeHandle& aidlNativeHandle) {
|
||||
return std::make_shared<const Handle>(NN_TRY(unvalidatedConvertHelper(aidlNativeHandle)));
|
||||
}
|
||||
|
||||
GeneralResult<ExecutionPreference> convert(
|
||||
@@ -422,7 +520,7 @@ GeneralResult<ExecutionPreference> convert(
|
||||
return validatedConvert(executionPreference);
|
||||
}
|
||||
|
||||
GeneralResult<Memory> convert(const aidl_hal::Memory& operand) {
|
||||
GeneralResult<SharedMemory> convert(const aidl_hal::Memory& operand) {
|
||||
return validatedConvert(operand);
|
||||
}
|
||||
|
||||
@@ -454,7 +552,7 @@ GeneralResult<std::vector<Operation>> convert(const std::vector<aidl_hal::Operat
|
||||
return unvalidatedConvert(operations);
|
||||
}
|
||||
|
||||
GeneralResult<std::vector<Memory>> convert(const std::vector<aidl_hal::Memory>& memories) {
|
||||
GeneralResult<std::vector<SharedMemory>> convert(const std::vector<aidl_hal::Memory>& memories) {
|
||||
return validatedConvert(memories);
|
||||
}
|
||||
|
||||
@@ -507,13 +605,11 @@ nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
|
||||
return halObject;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::SharedHandle& sharedHandle) {
|
||||
nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::Handle& handle) {
|
||||
common::NativeHandle aidlNativeHandle;
|
||||
aidlNativeHandle.fds.reserve(sharedHandle->fds.size());
|
||||
for (const auto& fd : sharedHandle->fds) {
|
||||
int dupFd = dup(fd.get());
|
||||
aidlNativeHandle.fds.reserve(handle.fds.size());
|
||||
for (const auto& fd : handle.fds) {
|
||||
const int dupFd = dup(fd.get());
|
||||
if (dupFd == -1) {
|
||||
// TODO(b/120417090): is ANEURALNETWORKS_UNEXPECTED_NULL the correct error to return
|
||||
// here?
|
||||
@@ -521,18 +617,71 @@ nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::SharedHandl
|
||||
}
|
||||
aidlNativeHandle.fds.emplace_back(dupFd);
|
||||
}
|
||||
aidlNativeHandle.ints = sharedHandle->ints;
|
||||
aidlNativeHandle.ints = handle.ints;
|
||||
return aidlNativeHandle;
|
||||
}
|
||||
|
||||
nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory& memory) {
|
||||
if (memory.size > std::numeric_limits<int64_t>::max()) {
|
||||
static nn::GeneralResult<common::NativeHandle> aidlHandleFromNativeHandle(
|
||||
const native_handle_t& handle) {
|
||||
common::NativeHandle aidlNativeHandle;
|
||||
|
||||
aidlNativeHandle.fds.reserve(handle.numFds);
|
||||
for (int i = 0; i < handle.numFds; ++i) {
|
||||
const int dupFd = dup(handle.data[i]);
|
||||
if (dupFd == -1) {
|
||||
return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to dup the fd";
|
||||
}
|
||||
aidlNativeHandle.fds.emplace_back(dupFd);
|
||||
}
|
||||
|
||||
aidlNativeHandle.ints = std::vector<int>(&handle.data[handle.numFds],
|
||||
&handle.data[handle.numFds + handle.numInts]);
|
||||
|
||||
return aidlNativeHandle;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::SharedHandle& sharedHandle) {
|
||||
CHECK(sharedHandle != nullptr);
|
||||
return unvalidatedConvert(*sharedHandle);
|
||||
}
|
||||
|
||||
nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory) {
|
||||
CHECK(memory != nullptr);
|
||||
if (memory->size > std::numeric_limits<int64_t>::max()) {
|
||||
return NN_ERROR() << "Memory size doesn't fit into int64_t.";
|
||||
}
|
||||
if (const auto* handle = std::get_if<nn::Handle>(&memory->handle)) {
|
||||
return Memory{
|
||||
.handle = NN_TRY(unvalidatedConvert(*handle)),
|
||||
.size = static_cast<int64_t>(memory->size),
|
||||
.name = memory->name,
|
||||
};
|
||||
}
|
||||
|
||||
const auto* ahwb = std::get<nn::HardwareBufferHandle>(memory->handle).get();
|
||||
AHardwareBuffer_Desc bufferDesc;
|
||||
AHardwareBuffer_describe(ahwb, &bufferDesc);
|
||||
|
||||
if (bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
|
||||
CHECK_EQ(memory->size, bufferDesc.width);
|
||||
CHECK_EQ(memory->name, "hardware_buffer_blob");
|
||||
} else {
|
||||
CHECK_EQ(memory->size, 0u);
|
||||
CHECK_EQ(memory->name, "hardware_buffer");
|
||||
}
|
||||
|
||||
const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
|
||||
if (nativeHandle == nullptr) {
|
||||
return NN_ERROR() << "unvalidatedConvert failed because AHardwareBuffer_getNativeHandle "
|
||||
"returned nullptr";
|
||||
}
|
||||
|
||||
return Memory{
|
||||
.handle = NN_TRY(unvalidatedConvert(memory.handle)),
|
||||
.size = static_cast<int64_t>(memory.size),
|
||||
.name = memory.name,
|
||||
.handle = NN_TRY(aidlHandleFromNativeHandle(*nativeHandle)),
|
||||
.size = static_cast<int64_t>(memory->size),
|
||||
.name = memory->name,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -558,7 +707,7 @@ nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputS
|
||||
.isSufficient = outputShape.isSufficient};
|
||||
}
|
||||
|
||||
nn::GeneralResult<Memory> convert(const nn::Memory& memory) {
|
||||
nn::GeneralResult<Memory> convert(const nn::SharedMemory& memory) {
|
||||
return validatedConvert(memory);
|
||||
}
|
||||
|
||||
|
||||
@@ -266,7 +266,7 @@ Model createModel(const TestModel& testModel) {
|
||||
copyTestBuffers(constCopies, operandValues.data());
|
||||
|
||||
// Shared memory.
|
||||
std::vector<nn::Memory> pools = {};
|
||||
std::vector<nn::SharedMemory> pools = {};
|
||||
if (constRefSize > 0) {
|
||||
const auto pool = nn::createSharedMemory(constRefSize).value();
|
||||
pools.push_back(pool);
|
||||
|
||||
@@ -135,7 +135,8 @@ void TestBlobAHWB::initialize(uint32_t size) {
|
||||
ASSERT_EQ(AHardwareBuffer_allocate(&desc, &mAhwb), 0);
|
||||
ASSERT_NE(mAhwb, nullptr);
|
||||
|
||||
const auto sharedMemory = nn::createSharedMemoryFromAHWB(*mAhwb).value();
|
||||
const auto sharedMemory =
|
||||
nn::createSharedMemoryFromAHWB(mAhwb, /*takeOwnership=*/false).value();
|
||||
mMapping = nn::map(sharedMemory).value();
|
||||
mPtr = static_cast<uint8_t*>(std::get<void*>(mMapping.pointer));
|
||||
CHECK_NE(mPtr, nullptr);
|
||||
|
||||
@@ -22,10 +22,12 @@ cc_library_static {
|
||||
export_include_dirs: ["include"],
|
||||
cflags: ["-Wthread-safety"],
|
||||
static_libs: [
|
||||
"libarect",
|
||||
"neuralnetworks_types",
|
||||
],
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libnativewindow",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -74,10 +74,12 @@ nn::GeneralResult<void> unflushDataFromSharedToPointer(
|
||||
std::vector<uint32_t> countNumberOfConsumers(size_t numberOfOperands,
|
||||
const std::vector<nn::Operation>& operations);
|
||||
|
||||
nn::GeneralResult<nn::Memory> createSharedMemoryFromHidlMemory(const hidl_memory& memory);
|
||||
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_handle> hidlHandleFromSharedHandle(const nn::SharedHandle& handle);
|
||||
nn::GeneralResult<nn::SharedHandle> sharedHandleFromNativeHandle(const native_handle_t* handle);
|
||||
nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences(
|
||||
const std::vector<nn::SyncFence>& fences);
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_HANDLE_ERROR_H
|
||||
#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_HANDLE_ERROR_H
|
||||
|
||||
#include <android/hidl/base/1.0/IBase.h>
|
||||
#include <hidl/HidlSupport.h>
|
||||
#include <nnapi/Result.h>
|
||||
@@ -50,7 +53,8 @@ nn::GeneralResult<Type> handleTransportError(const hardware::Return<Type>& ret)
|
||||
})
|
||||
|
||||
template <typename Type>
|
||||
nn::GeneralResult<Type> makeGeneralFailure(nn::Result<Type> result, nn::ErrorStatus status) {
|
||||
nn::GeneralResult<Type> makeGeneralFailure(
|
||||
nn::Result<Type> result, nn::ErrorStatus status = nn::ErrorStatus::GENERAL_FAILURE) {
|
||||
if (!result.has_value()) {
|
||||
return nn::error(status) << std::move(result).error();
|
||||
}
|
||||
@@ -75,7 +79,8 @@ nn::ExecutionResult<Type> makeExecutionFailure(nn::GeneralResult<Type> result) {
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
nn::ExecutionResult<Type> makeExecutionFailure(nn::Result<Type> result, nn::ErrorStatus status) {
|
||||
nn::ExecutionResult<Type> makeExecutionFailure(
|
||||
nn::Result<Type> result, nn::ErrorStatus status = nn::ErrorStatus::GENERAL_FAILURE) {
|
||||
return makeExecutionFailure(makeGeneralFailure(result, status));
|
||||
}
|
||||
|
||||
@@ -86,4 +91,6 @@ nn::ExecutionResult<Type> makeExecutionFailure(nn::Result<Type> result, nn::Erro
|
||||
} else \
|
||||
return NN_ERROR(canonical)
|
||||
|
||||
} // namespace android::hardware::neuralnetworks::utils
|
||||
} // namespace android::hardware::neuralnetworks::utils
|
||||
|
||||
#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_HANDLE_ERROR_H
|
||||
|
||||
@@ -31,9 +31,9 @@ class InvalidBuffer final : public nn::IBuffer {
|
||||
public:
|
||||
nn::Request::MemoryDomainToken getToken() const override;
|
||||
|
||||
nn::GeneralResult<void> copyTo(const nn::Memory& dst) const override;
|
||||
nn::GeneralResult<void> copyTo(const nn::SharedMemory& dst) const override;
|
||||
|
||||
nn::GeneralResult<void> copyFrom(const nn::Memory& src,
|
||||
nn::GeneralResult<void> copyFrom(const nn::SharedMemory& src,
|
||||
const nn::Dimensions& dimensions) const override;
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace android::hardware::neuralnetworks::utils {
|
||||
|
||||
class InvalidBurst final : public nn::IBurst {
|
||||
public:
|
||||
OptionalCacheHold cacheMemory(const nn::Memory& memory) const override;
|
||||
OptionalCacheHold cacheMemory(const nn::SharedMemory& memory) const override;
|
||||
|
||||
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
|
||||
const nn::Request& request, nn::MeasureTiming measure) const override;
|
||||
|
||||
@@ -46,9 +46,9 @@ class ResilientBuffer final : public nn::IBuffer {
|
||||
|
||||
nn::Request::MemoryDomainToken getToken() const override;
|
||||
|
||||
nn::GeneralResult<void> copyTo(const nn::Memory& dst) const override;
|
||||
nn::GeneralResult<void> copyTo(const nn::SharedMemory& dst) const override;
|
||||
|
||||
nn::GeneralResult<void> copyFrom(const nn::Memory& src,
|
||||
nn::GeneralResult<void> copyFrom(const nn::SharedMemory& src,
|
||||
const nn::Dimensions& dimensions) const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -44,7 +44,7 @@ class ResilientBurst final : public nn::IBurst,
|
||||
nn::SharedBurst getBurst() const;
|
||||
nn::GeneralResult<nn::SharedBurst> recover(const nn::IBurst* failingBurst) const;
|
||||
|
||||
OptionalCacheHold cacheMemory(const nn::Memory& memory) const override;
|
||||
OptionalCacheHold cacheMemory(const nn::SharedMemory& memory) const override;
|
||||
|
||||
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
|
||||
const nn::Request& request, nn::MeasureTiming measure) const override;
|
||||
|
||||
@@ -20,11 +20,14 @@
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <android/hardware_buffer.h>
|
||||
#include <hidl/HidlSupport.h>
|
||||
#include <nnapi/Result.h>
|
||||
#include <nnapi/SharedMemory.h>
|
||||
#include <nnapi/TypeUtils.h>
|
||||
#include <nnapi/Types.h>
|
||||
#include <nnapi/Validation.h>
|
||||
#include <vndk/hardware_buffer.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <any>
|
||||
@@ -203,13 +206,13 @@ nn::GeneralResult<std::reference_wrapper<const nn::Request>> flushDataFromPointe
|
||||
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())) {
|
||||
!std::holds_alternative<nn::SharedMemory>(maybeRequestInShared->pools.back())) {
|
||||
return {};
|
||||
}
|
||||
const auto& requestInShared = *maybeRequestInShared;
|
||||
|
||||
// Map the memory.
|
||||
const auto& outputMemory = std::get<nn::Memory>(requestInShared.pools.back());
|
||||
const auto& outputMemory = std::get<nn::SharedMemory>(requestInShared.pools.back());
|
||||
const auto [pointer, size, context] = NN_TRY(map(outputMemory));
|
||||
const uint8_t* constantPointer =
|
||||
std::visit([](const auto& o) { return static_cast<const uint8_t*>(o); }, pointer);
|
||||
@@ -248,44 +251,128 @@ std::vector<uint32_t> countNumberOfConsumers(size_t numberOfOperands,
|
||||
return nn::countNumberOfConsumers(numberOfOperands, operations);
|
||||
}
|
||||
|
||||
nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::SharedHandle& handle) {
|
||||
if (handle == nullptr) {
|
||||
return {};
|
||||
nn::GeneralResult<hidl_memory> createHidlMemoryFromSharedMemory(const nn::SharedMemory& memory) {
|
||||
if (memory == nullptr) {
|
||||
return NN_ERROR() << "Memory must be non-empty";
|
||||
}
|
||||
if (const auto* handle = std::get_if<nn::Handle>(&memory->handle)) {
|
||||
return hidl_memory(memory->name, NN_TRY(hidlHandleFromSharedHandle(*handle)), memory->size);
|
||||
}
|
||||
|
||||
const auto* ahwb = std::get<nn::HardwareBufferHandle>(memory->handle).get();
|
||||
AHardwareBuffer_Desc bufferDesc;
|
||||
AHardwareBuffer_describe(ahwb, &bufferDesc);
|
||||
|
||||
if (bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
|
||||
CHECK_EQ(memory->size, bufferDesc.width);
|
||||
CHECK_EQ(memory->name, "hardware_buffer_blob");
|
||||
} else {
|
||||
CHECK_EQ(memory->size, 0u);
|
||||
CHECK_EQ(memory->name, "hardware_buffer");
|
||||
}
|
||||
|
||||
const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
|
||||
const hidl_handle hidlHandle(nativeHandle);
|
||||
hidl_handle handle(hidlHandle);
|
||||
|
||||
return hidl_memory(memory->name, std::move(handle), memory->size);
|
||||
}
|
||||
|
||||
static uint32_t roundUpToMultiple(uint32_t value, uint32_t multiple) {
|
||||
return (value + multiple - 1) / multiple * multiple;
|
||||
}
|
||||
|
||||
nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory) {
|
||||
CHECK_LE(memory.size(), std::numeric_limits<uint32_t>::max());
|
||||
|
||||
if (memory.name() != "hardware_buffer_blob") {
|
||||
return std::make_shared<const nn::Memory>(nn::Memory{
|
||||
.handle = NN_TRY(sharedHandleFromNativeHandle(memory.handle())),
|
||||
.size = static_cast<uint32_t>(memory.size()),
|
||||
.name = memory.name(),
|
||||
});
|
||||
}
|
||||
|
||||
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 std::make_shared<const nn::Memory>(nn::Memory{
|
||||
.handle = nn::HardwareBufferHandle(hardwareBuffer, /*takeOwnership=*/true),
|
||||
.size = static_cast<uint32_t>(memory.size()),
|
||||
.name = memory.name(),
|
||||
});
|
||||
}
|
||||
|
||||
nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::Handle& handle) {
|
||||
std::vector<base::unique_fd> fds;
|
||||
fds.reserve(handle->fds.size());
|
||||
for (const auto& fd : handle->fds) {
|
||||
int dupFd = dup(fd);
|
||||
fds.reserve(handle.fds.size());
|
||||
for (const auto& fd : handle.fds) {
|
||||
const int dupFd = dup(fd);
|
||||
if (dupFd == -1) {
|
||||
return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to dup the fd";
|
||||
}
|
||||
fds.emplace_back(dupFd);
|
||||
}
|
||||
|
||||
native_handle_t* nativeHandle = native_handle_create(handle->fds.size(), handle->ints.size());
|
||||
constexpr size_t kIntMax = std::numeric_limits<int>::max();
|
||||
CHECK_LE(handle.fds.size(), kIntMax);
|
||||
CHECK_LE(handle.ints.size(), kIntMax);
|
||||
native_handle_t* nativeHandle = native_handle_create(static_cast<int>(handle.fds.size()),
|
||||
static_cast<int>(handle.ints.size()));
|
||||
if (nativeHandle == nullptr) {
|
||||
return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to create native_handle";
|
||||
}
|
||||
for (size_t i = 0; i < fds.size(); ++i) {
|
||||
nativeHandle->data[i] = fds[i].release();
|
||||
}
|
||||
std::copy(handle->ints.begin(), handle->ints.end(), &nativeHandle->data[nativeHandle->numFds]);
|
||||
std::copy(handle.ints.begin(), handle.ints.end(), &nativeHandle->data[nativeHandle->numFds]);
|
||||
|
||||
hidl_handle hidlHandle;
|
||||
hidlHandle.setTo(nativeHandle, /*shouldOwn=*/true);
|
||||
return hidlHandle;
|
||||
}
|
||||
|
||||
nn::GeneralResult<nn::SharedHandle> sharedHandleFromNativeHandle(const native_handle_t* handle) {
|
||||
nn::GeneralResult<nn::Handle> sharedHandleFromNativeHandle(const native_handle_t* handle) {
|
||||
if (handle == nullptr) {
|
||||
return nullptr;
|
||||
return NN_ERROR() << "sharedHandleFromNativeHandle failed because handle is nullptr";
|
||||
}
|
||||
|
||||
std::vector<base::unique_fd> fds;
|
||||
fds.reserve(handle->numFds);
|
||||
for (int i = 0; i < handle->numFds; ++i) {
|
||||
int dupFd = dup(handle->data[i]);
|
||||
const int dupFd = dup(handle->data[i]);
|
||||
if (dupFd == -1) {
|
||||
return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Failed to dup the fd";
|
||||
}
|
||||
@@ -295,18 +382,18 @@ nn::GeneralResult<nn::SharedHandle> sharedHandleFromNativeHandle(const native_ha
|
||||
std::vector<int> ints(&handle->data[handle->numFds],
|
||||
&handle->data[handle->numFds + handle->numInts]);
|
||||
|
||||
return std::make_shared<const nn::Handle>(nn::Handle{
|
||||
.fds = std::move(fds),
|
||||
.ints = std::move(ints),
|
||||
});
|
||||
return nn::Handle{.fds = std::move(fds), .ints = std::move(ints)};
|
||||
}
|
||||
|
||||
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) {
|
||||
handles[i] =
|
||||
NN_TRY(hal::utils::hidlHandleFromSharedHandle(syncFences[i].getSharedHandle()));
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -30,11 +30,11 @@ nn::Request::MemoryDomainToken InvalidBuffer::getToken() const {
|
||||
return nn::Request::MemoryDomainToken{};
|
||||
}
|
||||
|
||||
nn::GeneralResult<void> InvalidBuffer::copyTo(const nn::Memory& /*dst*/) const {
|
||||
nn::GeneralResult<void> InvalidBuffer::copyTo(const nn::SharedMemory& /*dst*/) const {
|
||||
return NN_ERROR() << "InvalidBuffer";
|
||||
}
|
||||
|
||||
nn::GeneralResult<void> InvalidBuffer::copyFrom(const nn::Memory& /*src*/,
|
||||
nn::GeneralResult<void> InvalidBuffer::copyFrom(const nn::SharedMemory& /*src*/,
|
||||
const nn::Dimensions& /*dimensions*/) const {
|
||||
return NN_ERROR() << "InvalidBuffer";
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
|
||||
namespace android::hardware::neuralnetworks::utils {
|
||||
|
||||
InvalidBurst::OptionalCacheHold InvalidBurst::cacheMemory(const nn::Memory& /*memory*/) const {
|
||||
InvalidBurst::OptionalCacheHold InvalidBurst::cacheMemory(
|
||||
const nn::SharedMemory& /*memory*/) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,12 +99,12 @@ nn::Request::MemoryDomainToken ResilientBuffer::getToken() const {
|
||||
return getBuffer()->getToken();
|
||||
}
|
||||
|
||||
nn::GeneralResult<void> ResilientBuffer::copyTo(const nn::Memory& dst) const {
|
||||
nn::GeneralResult<void> ResilientBuffer::copyTo(const nn::SharedMemory& dst) const {
|
||||
const auto fn = [&dst](const nn::IBuffer& buffer) { return buffer.copyTo(dst); };
|
||||
return protect(*this, fn);
|
||||
}
|
||||
|
||||
nn::GeneralResult<void> ResilientBuffer::copyFrom(const nn::Memory& src,
|
||||
nn::GeneralResult<void> ResilientBuffer::copyFrom(const nn::SharedMemory& src,
|
||||
const nn::Dimensions& dimensions) const {
|
||||
const auto fn = [&src, &dimensions](const nn::IBuffer& buffer) {
|
||||
return buffer.copyFrom(src, dimensions);
|
||||
|
||||
@@ -94,7 +94,8 @@ nn::GeneralResult<nn::SharedBurst> ResilientBurst::recover(const nn::IBurst* fai
|
||||
return mBurst;
|
||||
}
|
||||
|
||||
ResilientBurst::OptionalCacheHold ResilientBurst::cacheMemory(const nn::Memory& memory) const {
|
||||
ResilientBurst::OptionalCacheHold ResilientBurst::cacheMemory(
|
||||
const nn::SharedMemory& memory) const {
|
||||
return getBurst()->cacheMemory(memory);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,9 +27,9 @@ namespace android::nn {
|
||||
class MockBuffer final : public IBuffer {
|
||||
public:
|
||||
MOCK_METHOD(Request::MemoryDomainToken, getToken, (), (const, override));
|
||||
MOCK_METHOD(GeneralResult<void>, copyTo, (const Memory& dst), (const, override));
|
||||
MOCK_METHOD(GeneralResult<void>, copyFrom, (const Memory& src, const Dimensions& dimensions),
|
||||
(const, override));
|
||||
MOCK_METHOD(GeneralResult<void>, copyTo, (const SharedMemory& dst), (const, override));
|
||||
MOCK_METHOD(GeneralResult<void>, copyFrom,
|
||||
(const SharedMemory& src, const Dimensions& dimensions), (const, override));
|
||||
};
|
||||
|
||||
} // namespace android::nn
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <nnapi/SharedMemory.h>
|
||||
#include <nnapi/TypeUtils.h>
|
||||
#include <nnapi/Types.h>
|
||||
#include <nnapi/hal/ResilientBuffer.h>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include "MockBuffer.h"
|
||||
@@ -113,7 +115,8 @@ TEST(ResilientBufferTest, copyTo) {
|
||||
EXPECT_CALL(*mockBuffer, copyTo(_)).Times(1).WillOnce(Return(kNoError));
|
||||
|
||||
// run test
|
||||
const auto result = buffer->copyTo({});
|
||||
const nn::SharedMemory memory = std::make_shared<const nn::Memory>();
|
||||
const auto result = buffer->copyTo(memory);
|
||||
|
||||
// verify result
|
||||
ASSERT_TRUE(result.has_value())
|
||||
@@ -126,7 +129,8 @@ TEST(ResilientBufferTest, copyToError) {
|
||||
EXPECT_CALL(*mockBuffer, copyTo(_)).Times(1).WillOnce(kReturnGeneralFailure);
|
||||
|
||||
// run test
|
||||
const auto result = buffer->copyTo({});
|
||||
const nn::SharedMemory memory = std::make_shared<const nn::Memory>();
|
||||
const auto result = buffer->copyTo(memory);
|
||||
|
||||
// verify result
|
||||
ASSERT_FALSE(result.has_value());
|
||||
@@ -140,7 +144,8 @@ TEST(ResilientBufferTest, copyToDeadObjectFailedRecovery) {
|
||||
EXPECT_CALL(*mockBufferFactory, Call()).Times(1).WillOnce(kReturnGeneralFailure);
|
||||
|
||||
// run test
|
||||
const auto result = buffer->copyTo({});
|
||||
const nn::SharedMemory memory = std::make_shared<const nn::Memory>();
|
||||
const auto result = buffer->copyTo(memory);
|
||||
|
||||
// verify result
|
||||
ASSERT_FALSE(result.has_value());
|
||||
@@ -156,7 +161,8 @@ TEST(ResilientBufferTest, copyToDeadObjectSuccessfulRecovery) {
|
||||
EXPECT_CALL(*mockBufferFactory, Call()).Times(1).WillOnce(Return(recoveredMockBuffer));
|
||||
|
||||
// run test
|
||||
const auto result = buffer->copyTo({});
|
||||
const nn::SharedMemory memory = std::make_shared<const nn::Memory>();
|
||||
const auto result = buffer->copyTo(memory);
|
||||
|
||||
// verify result
|
||||
ASSERT_TRUE(result.has_value())
|
||||
@@ -169,7 +175,8 @@ TEST(ResilientBufferTest, copyFrom) {
|
||||
EXPECT_CALL(*mockBuffer, copyFrom(_, _)).Times(1).WillOnce(Return(kNoError));
|
||||
|
||||
// run test
|
||||
const auto result = buffer->copyFrom({}, {});
|
||||
const nn::SharedMemory memory = std::make_shared<const nn::Memory>();
|
||||
const auto result = buffer->copyFrom(memory, {});
|
||||
|
||||
// verify result
|
||||
ASSERT_TRUE(result.has_value())
|
||||
@@ -182,7 +189,8 @@ TEST(ResilientBufferTest, copyFromError) {
|
||||
EXPECT_CALL(*mockBuffer, copyFrom(_, _)).Times(1).WillOnce(kReturnGeneralFailure);
|
||||
|
||||
// run test
|
||||
const auto result = buffer->copyFrom({}, {});
|
||||
const nn::SharedMemory memory = std::make_shared<const nn::Memory>();
|
||||
const auto result = buffer->copyFrom(memory, {});
|
||||
|
||||
// verify result
|
||||
ASSERT_FALSE(result.has_value());
|
||||
@@ -196,7 +204,8 @@ TEST(ResilientBufferTest, copyFromDeadObjectFailedRecovery) {
|
||||
EXPECT_CALL(*mockBufferFactory, Call()).Times(1).WillOnce(kReturnGeneralFailure);
|
||||
|
||||
// run test
|
||||
const auto result = buffer->copyFrom({}, {});
|
||||
const nn::SharedMemory memory = std::make_shared<const nn::Memory>();
|
||||
const auto result = buffer->copyFrom(memory, {});
|
||||
|
||||
// verify result
|
||||
ASSERT_FALSE(result.has_value());
|
||||
@@ -212,7 +221,8 @@ TEST(ResilientBufferTest, copyFromDeadObjectSuccessfulRecovery) {
|
||||
EXPECT_CALL(*mockBufferFactory, Call()).Times(1).WillOnce(Return(recoveredMockBuffer));
|
||||
|
||||
// run test
|
||||
const auto result = buffer->copyFrom({}, {});
|
||||
const nn::SharedMemory memory = std::make_shared<const nn::Memory>();
|
||||
const auto result = buffer->copyFrom(memory, {});
|
||||
|
||||
// verify result
|
||||
ASSERT_TRUE(result.has_value())
|
||||
|
||||
Reference in New Issue
Block a user