From 08ee3f9287811e9087a5263c3176ce1439f70c2c Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Wed, 3 Feb 2021 15:15:43 -0800 Subject: [PATCH] Add missing validation for NN canonical types Bug: 177669661 Test: mma Test: NeuralNetworksTest_static Change-Id: Ic05c177f61a906a69bf82ff9c4d5bb8b0556d5ca --- .../1.0/utils/include/nnapi/hal/1.0/Utils.h | 14 +++ neuralnetworks/1.0/utils/src/Conversions.cpp | 38 +++----- .../1.1/utils/include/nnapi/hal/1.1/Utils.h | 13 +++ neuralnetworks/1.1/utils/src/Conversions.cpp | 42 +++------ .../1.2/utils/include/nnapi/hal/1.2/Utils.h | 15 +++ neuralnetworks/1.2/utils/src/Conversions.cpp | 92 +++++------------- .../1.3/utils/include/nnapi/hal/1.3/Utils.h | 20 ++++ neuralnetworks/1.3/utils/src/Conversions.cpp | 88 ++++-------------- .../include/nnapi/hal/aidl/Conversions.h | 6 +- .../aidl/utils/include/nnapi/hal/aidl/Utils.h | 17 ++++ neuralnetworks/aidl/utils/src/Conversions.cpp | 93 ++++++------------- .../aidl/vts/functional/ValidateModel.cpp | 2 +- 12 files changed, 176 insertions(+), 264 deletions(-) diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h index b695f48550..1baabdf562 100644 --- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h +++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h @@ -22,10 +22,15 @@ #include #include #include +#include #include +#include +#include namespace android::hardware::neuralnetworks::V1_0::utils { +constexpr auto kVersion = nn::Version::ANDROID_OC_MR1; + template nn::Result validate(const Type& halObject) { const auto maybeCanonical = nn::convert(halObject); @@ -44,6 +49,15 @@ bool valid(const Type& halObject) { return result.has_value(); } +template +nn::GeneralResult compliantVersion(const Type& canonical) { + const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical))); + if (version > kVersion) { + return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; + } + return {}; +} + template auto convertFromNonCanonical(const Type& nonCanonicalObject) -> decltype(convert(nn::convert(nonCanonicalObject).value())) { diff --git a/neuralnetworks/1.0/utils/src/Conversions.cpp b/neuralnetworks/1.0/utils/src/Conversions.cpp index 700b050ce7..c0498eb876 100644 --- a/neuralnetworks/1.0/utils/src/Conversions.cpp +++ b/neuralnetworks/1.0/utils/src/Conversions.cpp @@ -35,6 +35,8 @@ #include #include +#include "Utils.h" + namespace { template @@ -42,8 +44,6 @@ constexpr std::underlying_type_t underlyingType(Type value) { return static_cast>(value); } -constexpr auto kVersion = android::nn::Version::ANDROID_OC_MR1; - } // namespace namespace android::nn { @@ -53,13 +53,13 @@ using hardware::hidl_memory; using hardware::hidl_vec; template -using unvalidatedConvertOutput = +using UnvalidatedConvertOutput = std::decay_t()).value())>; template -GeneralResult>> unvalidatedConvert( +GeneralResult>> unvalidatedConvert( const hidl_vec& arguments) { - std::vector> canonical; + std::vector> canonical; canonical.reserve(arguments.size()); for (const auto& argument : arguments) { canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument))); @@ -68,16 +68,9 @@ GeneralResult>> unvalidatedConvert( } template -decltype(nn::unvalidatedConvert(std::declval())) validatedConvert(const Type& halObject) { +GeneralResult> validatedConvert(const Type& halObject) { auto canonical = NN_TRY(nn::unvalidatedConvert(halObject)); - const auto maybeVersion = validate(canonical); - if (!maybeVersion.has_value()) { - return error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } + NN_TRY(hal::V1_0::utils::compliantVersion(canonical)); return canonical; } @@ -248,13 +241,13 @@ namespace android::hardware::neuralnetworks::V1_0::utils { namespace { template -using unvalidatedConvertOutput = +using UnvalidatedConvertOutput = std::decay_t()).value())>; template -nn::GeneralResult>> unvalidatedConvert( +nn::GeneralResult>> unvalidatedConvert( const std::vector& arguments) { - hidl_vec> halObject(arguments.size()); + hidl_vec> halObject(arguments.size()); for (size_t i = 0; i < arguments.size(); ++i) { halObject[i] = NN_TRY(utils::unvalidatedConvert(arguments[i])); } @@ -262,15 +255,8 @@ nn::GeneralResult>> unvalidatedConvert( } template -decltype(utils::unvalidatedConvert(std::declval())) validatedConvert(const Type& canonical) { - const auto maybeVersion = nn::validate(canonical); - if (!maybeVersion.has_value()) { - return nn::error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } +nn::GeneralResult> validatedConvert(const Type& canonical) { + NN_TRY(compliantVersion(canonical)); return utils::unvalidatedConvert(canonical); } diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h index 09597a31f8..a8cf8cf7b9 100644 --- a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h +++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h @@ -22,12 +22,16 @@ #include #include #include +#include #include +#include #include +#include namespace android::hardware::neuralnetworks::V1_1::utils { constexpr auto kDefaultExecutionPreference = ExecutionPreference::FAST_SINGLE_ANSWER; +constexpr auto kVersion = nn::Version::ANDROID_P; template nn::Result validate(const Type& halObject) { @@ -47,6 +51,15 @@ bool valid(const Type& halObject) { return result.has_value(); } +template +nn::GeneralResult compliantVersion(const Type& canonical) { + const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical))); + if (version > kVersion) { + return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; + } + return {}; +} + template auto convertFromNonCanonical(const Type& nonCanonicalObject) -> decltype(convert(nn::convert(nonCanonicalObject).value())) { diff --git a/neuralnetworks/1.1/utils/src/Conversions.cpp b/neuralnetworks/1.1/utils/src/Conversions.cpp index d07f7d00bc..467ceb389b 100644 --- a/neuralnetworks/1.1/utils/src/Conversions.cpp +++ b/neuralnetworks/1.1/utils/src/Conversions.cpp @@ -35,11 +35,7 @@ #include #include -namespace { - -constexpr auto kVersion = android::nn::Version::ANDROID_P; - -} // namespace +#include "Utils.h" namespace android::nn { namespace { @@ -47,13 +43,13 @@ namespace { using hardware::hidl_vec; template -using unvalidatedConvertOutput = +using UnvalidatedConvertOutput = std::decay_t()).value())>; template -GeneralResult>> unvalidatedConvert( +GeneralResult>> unvalidatedConvert( const hidl_vec& arguments) { - std::vector> canonical; + std::vector> canonical; canonical.reserve(arguments.size()); for (const auto& argument : arguments) { canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument))); @@ -62,16 +58,9 @@ GeneralResult>> unvalidatedConvert( } template -decltype(nn::unvalidatedConvert(std::declval())) validatedConvert(const Type& halObject) { +GeneralResult> validatedConvert(const Type& halObject) { auto canonical = NN_TRY(nn::unvalidatedConvert(halObject)); - const auto maybeVersion = validate(canonical); - if (!maybeVersion.has_value()) { - return error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } + NN_TRY(hal::V1_1::utils::compliantVersion(canonical)); return canonical; } @@ -180,13 +169,13 @@ nn::GeneralResult unvalidatedConvert(const nn::SharedMemory& memory } template -using unvalidatedConvertOutput = +using UnvalidatedConvertOutput = std::decay_t()).value())>; template -nn::GeneralResult>> unvalidatedConvert( +nn::GeneralResult>> unvalidatedConvert( const std::vector& arguments) { - hidl_vec> halObject(arguments.size()); + hidl_vec> halObject(arguments.size()); for (size_t i = 0; i < arguments.size(); ++i) { halObject[i] = NN_TRY(unvalidatedConvert(arguments[i])); } @@ -194,16 +183,9 @@ nn::GeneralResult>> unvalidatedConvert( } template -decltype(utils::unvalidatedConvert(std::declval())) validatedConvert(const Type& canonical) { - const auto maybeVersion = nn::validate(canonical); - if (!maybeVersion.has_value()) { - return nn::error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } - return utils::unvalidatedConvert(canonical); +nn::GeneralResult> validatedConvert(const Type& canonical) { + NN_TRY(compliantVersion(canonical)); + return unvalidatedConvert(canonical); } } // anonymous namespace diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h index 323311439f..09691b65ee 100644 --- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h +++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h @@ -22,19 +22,25 @@ #include #include #include +#include #include +#include #include #include +#include +#include #include namespace android::hardware::neuralnetworks::V1_2::utils { using CacheToken = hidl_array(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>; +using V1_1::utils::kDefaultExecutionPreference; constexpr auto kDefaultMesaureTiming = MeasureTiming::NO; constexpr auto kNoTiming = Timing{.timeOnDevice = std::numeric_limits::max(), .timeInDriver = std::numeric_limits::max()}; +constexpr auto kVersion = nn::Version::ANDROID_Q; template nn::Result validate(const Type& halObject) { @@ -54,6 +60,15 @@ bool valid(const Type& halObject) { return result.has_value(); } +template +nn::GeneralResult compliantVersion(const Type& canonical) { + const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical))); + if (version > kVersion) { + return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; + } + return {}; +} + template auto convertFromNonCanonical(const Type& nonCanonicalObject) -> decltype(convert(nn::convert(nonCanonicalObject).value())) { diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp index 2c45583d0c..29945b75e5 100644 --- a/neuralnetworks/1.2/utils/src/Conversions.cpp +++ b/neuralnetworks/1.2/utils/src/Conversions.cpp @@ -37,6 +37,8 @@ #include #include +#include "Utils.h" + namespace { template @@ -45,50 +47,23 @@ constexpr std::underlying_type_t underlyingType(Type value) { } using HalDuration = std::chrono::duration; -constexpr auto kVersion = android::nn::Version::ANDROID_Q; -constexpr uint64_t kNoTiming = std::numeric_limits::max(); } // namespace namespace android::nn { namespace { -constexpr bool validOperandType(OperandType operandType) { - switch (operandType) { - case OperandType::FLOAT32: - case OperandType::INT32: - case OperandType::UINT32: - case OperandType::TENSOR_FLOAT32: - case OperandType::TENSOR_INT32: - case OperandType::TENSOR_QUANT8_ASYMM: - case OperandType::BOOL: - case OperandType::TENSOR_QUANT16_SYMM: - case OperandType::TENSOR_FLOAT16: - case OperandType::TENSOR_BOOL8: - case OperandType::FLOAT16: - case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL: - case OperandType::TENSOR_QUANT16_ASYMM: - case OperandType::TENSOR_QUANT8_SYMM: - case OperandType::OEM: - case OperandType::TENSOR_OEM_BYTE: - return true; - default: - break; - } - return isExtension(operandType); -} - using hardware::hidl_handle; using hardware::hidl_vec; template -using unvalidatedConvertOutput = +using UnvalidatedConvertOutput = std::decay_t()).value())>; template -GeneralResult>> unvalidatedConvertVec( +GeneralResult>> unvalidatedConvert( const hidl_vec& arguments) { - std::vector> canonical; + std::vector> canonical; canonical.reserve(arguments.size()); for (const auto& argument : arguments) { canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument))); @@ -97,29 +72,16 @@ GeneralResult>> unvalidatedConvertVec } template -GeneralResult>> unvalidatedConvert( - const hidl_vec& arguments) { - return unvalidatedConvertVec(arguments); -} - -template -decltype(nn::unvalidatedConvert(std::declval())) validatedConvert(const Type& halObject) { +GeneralResult> validatedConvert(const Type& halObject) { auto canonical = NN_TRY(nn::unvalidatedConvert(halObject)); - const auto maybeVersion = validate(canonical); - if (!maybeVersion.has_value()) { - return error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } + NN_TRY(hal::V1_2::utils::compliantVersion(canonical)); return canonical; } template -GeneralResult>> validatedConvert( +GeneralResult>> validatedConvert( const hidl_vec& arguments) { - std::vector> canonical; + std::vector> canonical; canonical.reserve(arguments.size()); for (const auto& argument : arguments) { canonical.push_back(NN_TRY(validatedConvert(argument))); @@ -145,8 +107,7 @@ GeneralResult unvalidatedConvert(const hal::V1_2::Capabilities& ca const bool validOperandTypes = std::all_of( capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(), [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) { - const auto maybeType = unvalidatedConvert(operandPerformance.type); - return !maybeType.has_value() ? false : validOperandType(maybeType.value()); + return validatedConvert(operandPerformance.type).has_value(); }); if (!validOperandTypes) { return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) @@ -275,6 +236,7 @@ GeneralResult unvalidatedConvert(const hal::V1_2::MeasureTiming& GeneralResult unvalidatedConvert(const hal::V1_2::Timing& timing) { constexpr uint64_t kMaxTiming = std::chrono::floor(Duration::max()).count(); constexpr auto convertTiming = [](uint64_t halTiming) -> OptionalDuration { + constexpr uint64_t kNoTiming = std::numeric_limits::max(); if (halTiming == kNoTiming) { return {}; } @@ -378,25 +340,19 @@ nn::GeneralResult unvalidatedConvert(const nn::SharedMemory& memory } template -using unvalidatedConvertOutput = +using UnvalidatedConvertOutput = std::decay_t()).value())>; template -nn::GeneralResult>> unvalidatedConvertVec( +nn::GeneralResult>> unvalidatedConvert( const std::vector& arguments) { - hidl_vec> halObject(arguments.size()); + hidl_vec> halObject(arguments.size()); for (size_t i = 0; i < arguments.size(); ++i) { halObject[i] = NN_TRY(unvalidatedConvert(arguments[i])); } return halObject; } -template -nn::GeneralResult>> unvalidatedConvert( - const std::vector& arguments) { - return unvalidatedConvertVec(arguments); -} - nn::GeneralResult makeExtraParams(nn::Operand::NoParams /*noParams*/) { return Operand::ExtraParams{}; } @@ -416,22 +372,15 @@ nn::GeneralResult makeExtraParams( } template -decltype(utils::unvalidatedConvert(std::declval())) validatedConvert(const Type& canonical) { - const auto maybeVersion = nn::validate(canonical); - if (!maybeVersion.has_value()) { - return nn::error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } - return utils::unvalidatedConvert(canonical); +nn::GeneralResult> validatedConvert(const Type& canonical) { + NN_TRY(compliantVersion(canonical)); + return unvalidatedConvert(canonical); } template -nn::GeneralResult>> validatedConvert( +nn::GeneralResult>> validatedConvert( const std::vector& arguments) { - hidl_vec> halObject(arguments.size()); + hidl_vec> halObject(arguments.size()); for (size_t i = 0; i < arguments.size(); ++i) { halObject[i] = NN_TRY(validatedConvert(arguments[i])); } @@ -469,7 +418,7 @@ nn::GeneralResult unvalidatedConvert(const nn::Capabilities& capab capabilities.operandPerformance.asVector().end(), std::back_inserter(operandPerformance), [](const nn::Capabilities::OperandPerformance& operandPerformance) { - return nn::validOperandType(operandPerformance.type); + return compliantVersion(operandPerformance.type).has_value(); }); return Capabilities{ @@ -570,6 +519,7 @@ nn::GeneralResult unvalidatedConvert(const nn::MeasureTiming& mea nn::GeneralResult unvalidatedConvert(const nn::Timing& timing) { constexpr auto convertTiming = [](nn::OptionalDuration canonicalTiming) -> uint64_t { + constexpr uint64_t kNoTiming = std::numeric_limits::max(); if (!canonicalTiming.has_value()) { return kNoTiming; } diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h index 3ce412cde6..1d76caaba6 100644 --- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h +++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h @@ -22,14 +22,25 @@ #include #include #include +#include #include +#include #include #include +#include #include +#include +#include namespace android::hardware::neuralnetworks::V1_3::utils { +using V1_1::utils::kDefaultExecutionPreference; +using V1_2::utils::CacheToken; +using V1_2::utils::kDefaultMesaureTiming; +using V1_2::utils::kNoTiming; + constexpr auto kDefaultPriority = Priority::MEDIUM; +constexpr auto kVersion = nn::Version::ANDROID_R; template nn::Result validate(const Type& halObject) { @@ -49,6 +60,15 @@ bool valid(const Type& halObject) { return result.has_value(); } +template +nn::GeneralResult compliantVersion(const Type& canonical) { + const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical))); + if (version > kVersion) { + return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; + } + return {}; +} + template auto convertFromNonCanonical(const Type& nonCanonicalObject) -> decltype(convert(nn::convert(nonCanonicalObject).value())) { diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp index 9788fe1b9d..baea9364f9 100644 --- a/neuralnetworks/1.3/utils/src/Conversions.cpp +++ b/neuralnetworks/1.3/utils/src/Conversions.cpp @@ -38,6 +38,8 @@ #include #include +#include "Utils.h" + namespace { template @@ -45,48 +47,21 @@ constexpr std::underlying_type_t underlyingType(Type value) { return static_cast>(value); } -constexpr auto kVersion = android::nn::Version::ANDROID_R; - } // namespace namespace android::nn { namespace { -constexpr auto validOperandType(nn::OperandType operandType) { - switch (operandType) { - case nn::OperandType::FLOAT32: - case nn::OperandType::INT32: - case nn::OperandType::UINT32: - case nn::OperandType::TENSOR_FLOAT32: - case nn::OperandType::TENSOR_INT32: - case nn::OperandType::TENSOR_QUANT8_ASYMM: - case nn::OperandType::BOOL: - case nn::OperandType::TENSOR_QUANT16_SYMM: - case nn::OperandType::TENSOR_FLOAT16: - case nn::OperandType::TENSOR_BOOL8: - case nn::OperandType::FLOAT16: - case nn::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL: - case nn::OperandType::TENSOR_QUANT16_ASYMM: - case nn::OperandType::TENSOR_QUANT8_SYMM: - case nn::OperandType::TENSOR_QUANT8_ASYMM_SIGNED: - case nn::OperandType::SUBGRAPH: - case nn::OperandType::OEM: - case nn::OperandType::TENSOR_OEM_BYTE: - return true; - } - return nn::isExtension(operandType); -} - using hardware::hidl_vec; template -using unvalidatedConvertOutput = +using UnvalidatedConvertOutput = std::decay_t()).value())>; template -GeneralResult>> unvalidatedConvertVec( +GeneralResult>> unvalidatedConvert( const hidl_vec& arguments) { - std::vector> canonical; + std::vector> canonical; canonical.reserve(arguments.size()); for (const auto& argument : arguments) { canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument))); @@ -95,29 +70,16 @@ GeneralResult>> unvalidatedConvertVec } template -GeneralResult>> unvalidatedConvert( - const hidl_vec& arguments) { - return unvalidatedConvertVec(arguments); -} - -template -decltype(nn::unvalidatedConvert(std::declval())) validatedConvert(const Type& halObject) { +GeneralResult> validatedConvert(const Type& halObject) { auto canonical = NN_TRY(nn::unvalidatedConvert(halObject)); - const auto maybeVersion = validate(canonical); - if (!maybeVersion.has_value()) { - return error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } + NN_TRY(hal::V1_3::utils::compliantVersion(canonical)); return canonical; } template -GeneralResult>> validatedConvert( +GeneralResult>> validatedConvert( const hidl_vec& arguments) { - std::vector> canonical; + std::vector> canonical; canonical.reserve(arguments.size()); for (const auto& argument : arguments) { canonical.push_back(NN_TRY(validatedConvert(argument))); @@ -143,8 +105,7 @@ GeneralResult unvalidatedConvert(const hal::V1_3::Capabilities& ca const bool validOperandTypes = std::all_of( capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(), [](const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) { - const auto maybeType = unvalidatedConvert(operandPerformance.type); - return !maybeType.has_value() ? false : validOperandType(maybeType.value()); + return validatedConvert(operandPerformance.type).has_value(); }); if (!validOperandTypes) { return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) @@ -401,25 +362,19 @@ nn::GeneralResult unvalidatedConvert( } template -using unvalidatedConvertOutput = +using UnvalidatedConvertOutput = std::decay_t()).value())>; template -nn::GeneralResult>> unvalidatedConvertVec( +nn::GeneralResult>> unvalidatedConvert( const std::vector& arguments) { - hidl_vec> halObject(arguments.size()); + hidl_vec> halObject(arguments.size()); for (size_t i = 0; i < arguments.size(); ++i) { halObject[i] = NN_TRY(unvalidatedConvert(arguments[i])); } return halObject; } -template -nn::GeneralResult>> unvalidatedConvert( - const std::vector& arguments) { - return unvalidatedConvertVec(arguments); -} - nn::GeneralResult makeMemoryPool(const nn::SharedMemory& memory) { Request::MemoryPool ret; ret.hidlMemory(NN_TRY(unvalidatedConvert(memory))); @@ -439,22 +394,15 @@ nn::GeneralResult makeMemoryPool(const nn::SharedBuffer& /* using utils::unvalidatedConvert; template -decltype(unvalidatedConvert(std::declval())) validatedConvert(const Type& canonical) { - const auto maybeVersion = nn::validate(canonical); - if (!maybeVersion.has_value()) { - return nn::error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } +nn::GeneralResult> validatedConvert(const Type& canonical) { + NN_TRY(compliantVersion(canonical)); return unvalidatedConvert(canonical); } template -nn::GeneralResult>> validatedConvert( +nn::GeneralResult>> validatedConvert( const std::vector& arguments) { - hidl_vec> halObject(arguments.size()); + hidl_vec> halObject(arguments.size()); for (size_t i = 0; i < arguments.size(); ++i) { halObject[i] = NN_TRY(validatedConvert(arguments[i])); } @@ -482,7 +430,7 @@ nn::GeneralResult unvalidatedConvert(const nn::Capabilities& capab capabilities.operandPerformance.asVector().end(), std::back_inserter(operandPerformance), [](const nn::Capabilities::OperandPerformance& operandPerformance) { - return nn::validOperandType(operandPerformance.type); + return compliantVersion(operandPerformance.type).has_value(); }); return Capabilities{ diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h index 4922a6ea1e..5eab9ffaf6 100644 --- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h +++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Conversions.h @@ -99,6 +99,9 @@ GeneralResult unvalidatedConvert( const ::aidl::android::hardware::common::NativeHandle& handle); GeneralResult unvalidatedConvert(const ndk::ScopedFileDescriptor& syncFence); +GeneralResult> unvalidatedConvert( + const std::vector& operations); + GeneralResult convert(const aidl_hal::Capabilities& capabilities); GeneralResult convert(const aidl_hal::DeviceType& deviceType); GeneralResult convert(const aidl_hal::ErrorStatus& errorStatus); @@ -106,16 +109,13 @@ GeneralResult convert( const aidl_hal::ExecutionPreference& executionPreference); GeneralResult convert(const aidl_hal::Memory& memory); GeneralResult convert(const aidl_hal::Model& model); -GeneralResult convert(const aidl_hal::Operand& operand); GeneralResult convert(const aidl_hal::OperandType& operandType); GeneralResult convert(const aidl_hal::Priority& priority); -GeneralResult convert(const aidl_hal::RequestMemoryPool& memoryPool); GeneralResult convert(const aidl_hal::Request& request); GeneralResult convert(const aidl_hal::Timing& timing); GeneralResult convert(const ndk::ScopedFileDescriptor& syncFence); GeneralResult> convert(const std::vector& extension); -GeneralResult> convert(const std::vector& outputShapes); GeneralResult> convert(const std::vector& memories); GeneralResult> convert( const std::vector& outputShapes); diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h index 58dcfe3af6..316d34fdfe 100644 --- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h +++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -48,6 +49,22 @@ bool valid(const Type& halObject) { return result.has_value(); } +template +nn::GeneralResult compliantVersion(const Type& canonical) { + const auto version = NN_TRY(::android::hardware::neuralnetworks::utils::makeGeneralFailure( + nn::validate(canonical))); + if (version > kVersion) { + return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; + } + return {}; +} + +template +auto convertFromNonCanonical(const Type& nonCanonicalObject) + -> decltype(convert(nn::convert(nonCanonicalObject).value())) { + return convert(NN_TRY(nn::convert(nonCanonicalObject))); +} + nn::GeneralResult clone(const Memory& memory); nn::GeneralResult clone(const Request& request); nn::GeneralResult clone(const RequestMemoryPool& requestPool); diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp index c47ba0ec1c..edd6982cb3 100644 --- a/neuralnetworks/aidl/utils/src/Conversions.cpp +++ b/neuralnetworks/aidl/utils/src/Conversions.cpp @@ -41,6 +41,8 @@ #include #include +#include "Utils.h" + #define VERIFY_NON_NEGATIVE(value) \ while (UNLIKELY(value < 0)) return NN_ERROR() @@ -53,7 +55,6 @@ constexpr std::underlying_type_t underlyingType(Type value) { return static_cast>(value); } -constexpr auto kVersion = android::nn::Version::ANDROID_S; constexpr int64_t kNoTiming = -1; } // namespace @@ -63,32 +64,6 @@ namespace { using ::aidl::android::hardware::common::NativeHandle; -constexpr auto validOperandType(nn::OperandType operandType) { - switch (operandType) { - case nn::OperandType::FLOAT32: - case nn::OperandType::INT32: - case nn::OperandType::UINT32: - case nn::OperandType::TENSOR_FLOAT32: - case nn::OperandType::TENSOR_INT32: - case nn::OperandType::TENSOR_QUANT8_ASYMM: - case nn::OperandType::BOOL: - case nn::OperandType::TENSOR_QUANT16_SYMM: - case nn::OperandType::TENSOR_FLOAT16: - case nn::OperandType::TENSOR_BOOL8: - case nn::OperandType::FLOAT16: - case nn::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL: - case nn::OperandType::TENSOR_QUANT16_ASYMM: - case nn::OperandType::TENSOR_QUANT8_SYMM: - case nn::OperandType::TENSOR_QUANT8_ASYMM_SIGNED: - case nn::OperandType::SUBGRAPH: - return true; - case nn::OperandType::OEM: - case nn::OperandType::TENSOR_OEM_BYTE: - return false; - } - return nn::isExtension(operandType); -} - template using UnvalidatedConvertOutput = std::decay_t()).value())>; @@ -113,14 +88,7 @@ GeneralResult>> unvalidatedConvert( template GeneralResult> validatedConvert(const Type& halObject) { auto canonical = NN_TRY(nn::unvalidatedConvert(halObject)); - const auto maybeVersion = validate(canonical); - if (!maybeVersion.has_value()) { - return error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } + NN_TRY(aidl_hal::utils::compliantVersion(canonical)); return canonical; } @@ -185,13 +153,21 @@ static GeneralResult nativeHandleFromAidlHandle(const Native GeneralResult unvalidatedConvert(const aidl_hal::OperandType& operandType) { VERIFY_NON_NEGATIVE(underlyingType(operandType)) << "Negative operand types are not allowed."; - return static_cast(operandType); + const auto canonical = static_cast(operandType); + if (canonical == OperandType::OEM || canonical == OperandType::TENSOR_OEM_BYTE) { + return NN_ERROR() << "Unable to convert invalid OperandType " << canonical; + } + return canonical; } GeneralResult unvalidatedConvert(const aidl_hal::OperationType& operationType) { VERIFY_NON_NEGATIVE(underlyingType(operationType)) << "Negative operation types are not allowed."; - return static_cast(operationType); + const auto canonical = static_cast(operationType); + if (canonical == OperationType::OEM_OPERATION) { + return NN_ERROR() << "Unable to convert invalid OperationType OEM_OPERATION"; + } + return canonical; } GeneralResult unvalidatedConvert(const aidl_hal::DeviceType& deviceType) { @@ -206,8 +182,7 @@ GeneralResult unvalidatedConvert(const aidl_hal::Capabilities& cap const bool validOperandTypes = std::all_of( capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(), [](const aidl_hal::OperandPerformance& operandPerformance) { - const auto maybeType = unvalidatedConvert(operandPerformance.type); - return !maybeType.has_value() ? false : validOperandType(maybeType.value()); + return validatedConvert(operandPerformance.type).has_value(); }); if (!validOperandTypes) { return NN_ERROR() << "Invalid OperandType when unvalidatedConverting OperandPerformance in " @@ -534,6 +509,11 @@ GeneralResult unvalidatedConvert(const NativeHandle& aidlNativeHan return std::make_shared(NN_TRY(unvalidatedConvertHelper(aidlNativeHandle))); } +GeneralResult> unvalidatedConvert( + const std::vector& operations) { + return unvalidatedConvertVec(operations); +} + GeneralResult unvalidatedConvert(const ndk::ScopedFileDescriptor& syncFence) { auto duplicatedFd = NN_TRY(dupFd(syncFence.get())); return SyncFence::create(std::move(duplicatedFd)); @@ -564,22 +544,14 @@ GeneralResult convert(const aidl_hal::Model& model) { return validatedConvert(model); } -GeneralResult convert(const aidl_hal::Operand& operand) { - return unvalidatedConvert(operand); -} - GeneralResult convert(const aidl_hal::OperandType& operandType) { - return unvalidatedConvert(operandType); + return validatedConvert(operandType); } GeneralResult convert(const aidl_hal::Priority& priority) { return validatedConvert(priority); } -GeneralResult convert(const aidl_hal::RequestMemoryPool& memoryPool) { - return unvalidatedConvert(memoryPool); -} - GeneralResult convert(const aidl_hal::Request& request) { return validatedConvert(request); } @@ -589,17 +561,13 @@ GeneralResult convert(const aidl_hal::Timing& timing) { } GeneralResult convert(const ndk::ScopedFileDescriptor& syncFence) { - return unvalidatedConvert(syncFence); + return validatedConvert(syncFence); } GeneralResult> convert(const std::vector& extension) { return validatedConvert(extension); } -GeneralResult> convert(const std::vector& operations) { - return unvalidatedConvert(operations); -} - GeneralResult> convert(const std::vector& memories) { return validatedConvert(memories); } @@ -644,14 +612,7 @@ nn::GeneralResult>> unvalidatedConver template nn::GeneralResult> validatedConvert(const Type& canonical) { - const auto maybeVersion = nn::validate(canonical); - if (!maybeVersion.has_value()) { - return nn::error() << maybeVersion.error(); - } - const auto version = maybeVersion.value(); - if (version > kVersion) { - return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion; - } + NN_TRY(compliantVersion(canonical)); return utils::unvalidatedConvert(canonical); } @@ -797,6 +758,9 @@ nn::GeneralResult unvalidatedConvert( } nn::GeneralResult unvalidatedConvert(const nn::OperandType& operandType) { + if (operandType == nn::OperandType::OEM || operandType == nn::OperandType::TENSOR_OEM_BYTE) { + return NN_ERROR() << "Unable to convert invalid OperandType " << operandType; + } return static_cast(operandType); } @@ -864,6 +828,9 @@ nn::GeneralResult unvalidatedConvert(const nn::Operand& operand) { } nn::GeneralResult unvalidatedConvert(const nn::OperationType& operationType) { + if (operationType == nn::OperationType::OEM_OPERATION) { + return NN_ERROR() << "Unable to convert invalid OperationType OEM_OPERATION"; + } return static_cast(operationType); } @@ -1004,7 +971,7 @@ nn::GeneralResult unvalidatedConvertCache( } nn::GeneralResult> convert(const nn::CacheToken& cacheToken) { - return unvalidatedConvert(cacheToken); + return validatedConvert(cacheToken); } nn::GeneralResult convert(const nn::BufferDesc& bufferDesc) { @@ -1076,7 +1043,7 @@ nn::GeneralResult> convert( nn::GeneralResult> convert( const std::vector& syncFences) { - return unvalidatedConvert(syncFences); + return validatedConvert(syncFences); } nn::GeneralResult> toSigned(const std::vector& vec) { diff --git a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp index 6d84e1ed7b..94d3daf6bb 100644 --- a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp +++ b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp @@ -1312,7 +1312,7 @@ static void mutateExecutionPriorityTest(const std::shared_ptr& device, void validateModel(const std::shared_ptr& device, const Model& model) { const auto numberOfConsumers = nn::countNumberOfConsumers(model.main.operands.size(), - nn::convert(model.main.operations).value()) + nn::unvalidatedConvert(model.main.operations).value()) .value(); mutateExecutionOrderTest(device, model, numberOfConsumers); mutateOperandTypeTest(device, model);