| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "Utils" |
| |
| #include "LegacyHalUtils.h" |
| |
| #include <nnapi/TypeUtils.h> |
| #include <nnapi/hal/1.0/Conversions.h> |
| #include <nnapi/hal/1.1/Conversions.h> |
| #include <nnapi/hal/1.2/Conversions.h> |
| #include <nnapi/hal/1.3/Conversions.h> |
| #include <nnapi/hal/aidl/Conversions.h> |
| |
| #include <algorithm> |
| #include <limits> |
| #include <set> |
| #include <string> |
| #include <tuple> |
| #include <type_traits> |
| #include <utility> |
| #include <vector> |
| |
| #include "CpuExecutor.h" |
| #include "NeuralNetworks.h" |
| #include "ValidateHal.h" |
| |
| namespace android { |
| namespace nn { |
| |
| constexpr V1_0::PerformanceInfo kNoPerformanceInfo = {.execTime = FLT_MAX, .powerUsage = FLT_MAX}; |
| |
| template <typename Type> |
| static Type handleError(GeneralResult<Type> result) { |
| CHECK(result.has_value()) << "Unhandled error (" << result.error().code |
| << "): " << result.error().message; |
| return std::move(result).value(); |
| } |
| |
| LegacyOptionalTimePoint makeDeadline(const V1_3::OptionalTimePoint& timePoint) { |
| using Disc = V1_3::OptionalTimePoint::hidl_discriminator; |
| if (timePoint.getDiscriminator() == Disc::none) { |
| return LegacyOptionalTimePoint{}; |
| } |
| const uint64_t count = timePoint.nanosecondsSinceEpoch(); |
| return LegacyTimePoint{LegacyDuration{count}}; |
| } |
| |
| LegacyOptionalTimePoint makeDeadline(const V1_3::OptionalTimeoutDuration& optionalDuration) { |
| if (optionalDuration.getDiscriminator() == |
| V1_3::OptionalTimeoutDuration::hidl_discriminator::none) { |
| return LegacyOptionalTimePoint{}; |
| } |
| |
| const auto duration = LegacyDuration{optionalDuration.nanoseconds()}; |
| constexpr auto kMaxTime = LegacyTimePoint::max(); |
| const auto currentTime = LegacyClock::now(); |
| |
| // If there would be an overflow, use the max value. |
| if (duration > kMaxTime - currentTime) { |
| return kMaxTime; |
| } |
| return currentTime + duration; |
| } |
| |
| bool hasDeadlinePassed(const LegacyOptionalTimePoint& deadline) { |
| if (!deadline.has_value()) { |
| return false; |
| } |
| return LegacyClock::now() >= *deadline; |
| } |
| |
| bool isExtensionOperandType(V1_3::OperandType type) { |
| return isExtensionOperandType(static_cast<OperandType>(type)); |
| } |
| |
| bool isExtensionOperationType(V1_3::OperationType type) { |
| return isExtensionOperationType(static_cast<OperationType>(type)); |
| } |
| |
| std::string getOperandTypeName(V1_3::OperandType type) { |
| return toString(type); |
| } |
| |
| std::string getOperationName(V1_3::OperationType type) { |
| return toString(type); |
| } |
| |
| uint32_t nonExtensionOperandSizeOfData(V1_3::OperandType type, |
| const std::vector<uint32_t>& dimensions) { |
| return nonExtensionOperandSizeOfData(uncheckedConvert(type), dimensions); |
| } |
| |
| bool nonExtensionOperandSizeOfDataOverflowsUInt32(V1_3::OperandType type, |
| const std::vector<uint32_t>& dimensions) { |
| return nonExtensionOperandSizeOfDataOverflowsUInt32(uncheckedConvert(type), dimensions); |
| } |
| |
| bool tensorHasUnspecifiedDimensions(V1_3::OperandType type, |
| const std::vector<uint32_t>& dimensions) { |
| return tensorHasUnspecifiedDimensions(static_cast<int>(type), dimensions.data(), |
| dimensions.size()); |
| } |
| |
| bool tensorHasUnspecifiedDimensions(const V1_3::Operand& operand) { |
| return tensorHasUnspecifiedDimensions(static_cast<int>(operand.type), operand.dimensions.data(), |
| operand.dimensions.size()); |
| } |
| |
| void logModelToInfo(const V1_0::Model& model) { |
| LOG(INFO) << "V1_0::Model start"; |
| LOG(INFO) << "operands" << toString(model.operands); |
| LOG(INFO) << "operations" << toString(model.operations); |
| LOG(INFO) << "inputIndexes" << toString(model.inputIndexes); |
| LOG(INFO) << "outputIndexes" << toString(model.outputIndexes); |
| LOG(INFO) << "operandValues size" << model.operandValues.size(); |
| LOG(INFO) << "pools" << SHOW_IF_DEBUG(toString(model.pools)); |
| } |
| |
| void logModelToInfo(const V1_1::Model& model) { |
| LOG(INFO) << "V1_1::Model start"; |
| LOG(INFO) << "operands" << toString(model.operands); |
| LOG(INFO) << "operations" << toString(model.operations); |
| LOG(INFO) << "inputIndexes" << toString(model.inputIndexes); |
| LOG(INFO) << "outputIndexes" << toString(model.outputIndexes); |
| LOG(INFO) << "operandValues size " << model.operandValues.size(); |
| LOG(INFO) << "pools" << SHOW_IF_DEBUG(toString(model.pools)); |
| } |
| |
| void logModelToInfo(const V1_2::Model& model) { |
| LOG(INFO) << "V1_2::Model start"; |
| LOG(INFO) << "operands" << toString(model.operands); |
| LOG(INFO) << "operations" << toString(model.operations); |
| LOG(INFO) << "inputIndexes" << toString(model.inputIndexes); |
| LOG(INFO) << "outputIndexes" << toString(model.outputIndexes); |
| LOG(INFO) << "operandValues size" << model.operandValues.size(); |
| LOG(INFO) << "pools" << SHOW_IF_DEBUG(toString(model.pools)); |
| LOG(INFO) << "relaxComputationFloat32toFloat16" << model.relaxComputationFloat32toFloat16; |
| LOG(INFO) << "extensionNameToPrefix" << toString(model.extensionNameToPrefix); |
| } |
| |
| static void logSubgraphToInfo(std::string label, const V1_3::Subgraph& subgraph) { |
| LOG(INFO) << label << ".operands" << toString(subgraph.operands); |
| LOG(INFO) << label << ".operations" << toString(subgraph.operations); |
| LOG(INFO) << label << ".inputIndexes" << toString(subgraph.inputIndexes); |
| LOG(INFO) << label << ".outputIndexes" << toString(subgraph.outputIndexes); |
| } |
| |
| void logModelToInfo(const V1_3::Model& model) { |
| LOG(INFO) << "V1_3::Model start"; |
| logSubgraphToInfo("main", model.main); |
| for (uint32_t i = 0, n = model.referenced.size(); i < n; ++i) { |
| logSubgraphToInfo("referenced[" + std::to_string(i) + "]", model.referenced[i]); |
| } |
| LOG(INFO) << "operandValues size " << model.operandValues.size(); |
| LOG(INFO) << "pools" << SHOW_IF_DEBUG(toString(model.pools)); |
| LOG(INFO) << "relaxComputationFloat32toFloat16 " << model.relaxComputationFloat32toFloat16; |
| LOG(INFO) << "extensionNameToPrefix" << toString(model.extensionNameToPrefix); |
| } |
| |
| bool validateOperandSymmPerChannelQuantParams( |
| const V1_3::Operand& halOperand, |
| const ANeuralNetworksSymmPerChannelQuantParams& channelQuant, const char* tag) { |
| if (halOperand.type != V1_3::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL) { |
| return false; |
| } |
| |
| NN_RET_CHECK_LT(channelQuant.channelDim, halOperand.dimensions.size()) << tag; |
| NN_RET_CHECK(channelQuant.scales != nullptr) << tag; |
| NN_RET_CHECK_EQ(channelQuant.scaleCount, halOperand.dimensions[channelQuant.channelDim]) << tag; |
| NN_RET_CHECK_NE(halOperand.dimensions[channelQuant.channelDim], 0u) |
| << tag << " channel dimension " << channelQuant.channelDim << " is underspecified"; |
| for (uint32_t i = 0; i < halOperand.dimensions[channelQuant.channelDim]; i++) { |
| NN_RET_CHECK_GT(channelQuant.scales[i], 0.0f) << tag << " invalid scaleArray[" << i << "]"; |
| } |
| return true; |
| } |
| |
| static int validateHalVersion(ANeuralNetworksOperationType opType, HalVersion halVersion, |
| HalVersion minSupportedHalVersion) { |
| if (halVersion < minSupportedHalVersion) { |
| LOG(ERROR) << "The given inputs and outputs for operation " << opType |
| << " are only supported in " << minSupportedHalVersion |
| << " and later (validating using " << halVersion << ")"; |
| return ANEURALNETWORKS_BAD_DATA; |
| } |
| return ANEURALNETWORKS_NO_ERROR; |
| } |
| |
| static inline int validateOperation(ANeuralNetworksOperationType opType, uint32_t inputCount, |
| const uint32_t* inputIndexes, uint32_t outputCount, |
| const uint32_t* outputIndexes, |
| const std::vector<Operand>& operands, HalVersion halVersion) { |
| if (opType == ANEURALNETWORKS_IF || opType == ANEURALNETWORKS_WHILE) { |
| NN_RETURN_IF_ERROR(validateHalVersion(opType, halVersion, HalVersion::V1_3)); |
| LOG(ERROR) << "This validateOperation() overload does not support control flow"; |
| return ANEURALNETWORKS_BAD_DATA; |
| } |
| return validateOperation(opType, inputCount, inputIndexes, outputCount, outputIndexes, operands, |
| halVersion, {}); |
| } |
| |
| V1_3::ErrorStatus convertResultCodeToHalErrorStatus(int resultCode) { |
| return convertToV1_3(convertResultCodeToErrorStatus(resultCode)); |
| } |
| |
| int convertErrorStatusToResultCode(V1_3::ErrorStatus status) { |
| return convertErrorStatusToResultCode(uncheckedConvert(status)); |
| } |
| |
| std::tuple<int, std::vector<OutputShape>, Timing> getExecutionResult( |
| V1_3::ErrorStatus status, const hardware::hidl_vec<V1_2::OutputShape>& outputShapes, |
| const V1_2::Timing& timing) { |
| return getExecutionResult(uncheckedConvert(status), uncheckedConvert(outputShapes), |
| uncheckedConvert(timing)); |
| } |
| |
| // Capabilities::operandPerformance utilities. |
| // The field Capabilities::operandPerformance is a vector sorted by the field |
| // Capabilities::OperandPerformance::type. |
| |
| template <HalVersion version> |
| hardware::hidl_vec<VersionedOperandPerformance<version>> nonExtensionOperandPerformance( |
| V1_0::PerformanceInfo perf) { |
| using OpPerf = VersionedOperandPerformance<version>; |
| |
| // Note: range presents enumerators in declaration order, not in numerical order. |
| static constexpr hardware::hidl_enum_range<VersionedOperandType<version>> kOperandTypeRange; |
| |
| std::vector<OpPerf> ret; |
| ret.reserve(kOperandTypeRange.end() - kOperandTypeRange.begin()); |
| for (VersionedOperandType<version> type : kOperandTypeRange) { |
| if (static_cast<V1_3::OperandType>(type) != V1_3::OperandType::SUBGRAPH) { |
| ret.push_back(OpPerf{type, perf}); |
| } |
| } |
| std::sort(ret.begin(), ret.end(), |
| [](const OpPerf& a, const OpPerf& b) { return a.type < b.type; }); |
| |
| return ret; |
| } |
| |
| template hardware::hidl_vec<V1_2::Capabilities::OperandPerformance> |
| nonExtensionOperandPerformance<HalVersion::V1_2>(V1_0::PerformanceInfo perf); |
| template hardware::hidl_vec<V1_3::Capabilities::OperandPerformance> |
| nonExtensionOperandPerformance<HalVersion::V1_3>(V1_0::PerformanceInfo perf); |
| |
| template <HalVersion version> |
| void update(hardware::hidl_vec<VersionedOperandPerformance<version>>* operandPerformance, |
| VersionedOperandType<version> type, V1_0::PerformanceInfo perf) { |
| CHECK(operandPerformance != nullptr); |
| const auto it = |
| std::lower_bound(operandPerformance->begin(), operandPerformance->end(), type, |
| [](const VersionedOperandPerformance<version>& perf, |
| VersionedOperandType<version> type) { return perf.type < type; }); |
| CHECK(it != operandPerformance->end()) |
| << toString(type) << " not in " << toString(*operandPerformance); |
| it->info = perf; |
| } |
| |
| void update(hardware::hidl_vec<V1_2::Capabilities::OperandPerformance>* operandPerformance, |
| V1_2::OperandType type, V1_0::PerformanceInfo perf) { |
| update<HalVersion::V1_2>(operandPerformance, type, perf); |
| } |
| void update(hardware::hidl_vec<V1_3::Capabilities::OperandPerformance>* operandPerformance, |
| V1_3::OperandType type, V1_0::PerformanceInfo perf) { |
| update<HalVersion::V1_3>(operandPerformance, type, perf); |
| } |
| |
| template <HalVersion version> |
| V1_0::PerformanceInfo lookup( |
| const hardware::hidl_vec<VersionedOperandPerformance<version>>& operandPerformance, |
| VersionedOperandType<version> type) { |
| const auto it = std::lower_bound(operandPerformance.begin(), operandPerformance.end(), type, |
| [](const VersionedOperandPerformance<version>& perf, |
| VersionedOperandType<version> type) { |
| return static_cast<V1_3::OperandType>(perf.type) < |
| static_cast<V1_3::OperandType>(type); |
| }); |
| if (it == operandPerformance.end()) { |
| LOG(WARNING) << "No PerformanceInfo for " << toString(type); |
| return kNoPerformanceInfo; |
| } else { |
| return it->info; |
| } |
| } |
| |
| V1_0::PerformanceInfo lookup( |
| const hardware::hidl_vec<V1_2::Capabilities::OperandPerformance>& operandPerformance, |
| V1_2::OperandType type) { |
| return lookup<HalVersion::V1_2>(operandPerformance, type); |
| } |
| V1_0::PerformanceInfo lookup( |
| const hardware::hidl_vec<V1_3::Capabilities::OperandPerformance>& operandPerformance, |
| V1_3::OperandType type) { |
| CHECK(type != V1_3::OperandType::SUBGRAPH) |
| << "Use Capabilities::ifPerformance or Capabilities::whilePerformance"; |
| return lookup<HalVersion::V1_3>(operandPerformance, type); |
| } |
| |
| bool setRunTimePoolInfosFromHidlMemories(std::vector<RunTimePoolInfo>* poolInfos, |
| const hardware::hidl_vec<hardware::hidl_memory>& pools) { |
| return setRunTimePoolInfosFromCanonicalMemories(poolInfos, uncheckedConvert(pools)); |
| } |
| |
| // Versioning |
| |
| // In Android P, most data types are treated as having the same performance as TENSOR_QUANT8_ASYMM. |
| // This array must be in sorted order. |
| static const V1_3::OperandType kQuantized8PerformanceConsistentWithP[] = { |
| V1_3::OperandType::INT32, V1_3::OperandType::UINT32, V1_3::OperandType::TENSOR_INT32, |
| V1_3::OperandType::OEM, V1_3::OperandType::TENSOR_OEM_BYTE}; |
| |
| static bool isQuantized8PerformanceConsistentWithP(const V1_2::Capabilities& capabilities) { |
| const V1_0::PerformanceInfo quantized8Performance = |
| lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_QUANT8_ASYMM); |
| return std::all_of(std::begin(kQuantized8PerformanceConsistentWithP), |
| std::end(kQuantized8PerformanceConsistentWithP), |
| [quantized8Performance, &capabilities](V1_3::OperandType type) { |
| return quantized8Performance == |
| lookup(capabilities.operandPerformance, |
| static_cast<V1_2::OperandType>(type)); |
| }); |
| } |
| |
| static bool isQuantized8PerformanceConsistentWithP(const V1_3::Capabilities& capabilities) { |
| const V1_0::PerformanceInfo quantized8Performance = |
| lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM); |
| return std::all_of(std::begin(kQuantized8PerformanceConsistentWithP), |
| std::end(kQuantized8PerformanceConsistentWithP), |
| [quantized8Performance, &capabilities](V1_3::OperandType type) { |
| return quantized8Performance == |
| lookup(capabilities.operandPerformance, type); |
| }); |
| } |
| |
| static hardware::hidl_vec<V1_2::Capabilities::OperandPerformance> |
| makeQuantized8PerformanceConsistentWithP(V1_0::PerformanceInfo quantized8Performance) { |
| hardware::hidl_vec<V1_2::Capabilities::OperandPerformance> ret( |
| std::size(kQuantized8PerformanceConsistentWithP)); |
| std::transform(std::begin(kQuantized8PerformanceConsistentWithP), |
| std::end(kQuantized8PerformanceConsistentWithP), ret.begin(), |
| [quantized8Performance]( |
| V1_3::OperandType type) -> V1_2::Capabilities::OperandPerformance { |
| return {static_cast<V1_2::OperandType>(type), quantized8Performance}; |
| }); |
| return ret; |
| } |
| |
| bool compliantWithV1_0(const V1_0::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_0(const V1_1::Capabilities& capabilities) { |
| return capabilities.relaxedFloat32toFloat16Performance == capabilities.float32Performance; |
| } |
| |
| bool compliantWithV1_0(const V1_2::Capabilities& capabilities) { |
| const V1_0::PerformanceInfo perfTensorFloat32 = |
| lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_FLOAT32); |
| const V1_0::PerformanceInfo perfFloat32 = |
| lookup(capabilities.operandPerformance, V1_2::OperandType::FLOAT32); |
| if (perfTensorFloat32 != perfFloat32 || |
| perfTensorFloat32 != capabilities.relaxedFloat32toFloat16PerformanceTensor || |
| perfFloat32 != capabilities.relaxedFloat32toFloat16PerformanceScalar) { |
| return false; |
| } |
| |
| return isQuantized8PerformanceConsistentWithP(capabilities); |
| } |
| |
| bool compliantWithV1_0(const V1_3::Capabilities& capabilities) { |
| const V1_0::PerformanceInfo perfTensorFloat32 = |
| lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32); |
| const V1_0::PerformanceInfo perfFloat32 = |
| lookup(capabilities.operandPerformance, V1_3::OperandType::FLOAT32); |
| if (perfTensorFloat32 != perfFloat32 || |
| perfTensorFloat32 != capabilities.relaxedFloat32toFloat16PerformanceTensor || |
| perfFloat32 != capabilities.relaxedFloat32toFloat16PerformanceScalar) { |
| return false; |
| } |
| |
| return isQuantized8PerformanceConsistentWithP(capabilities); |
| } |
| |
| bool compliantWithV1_1(const V1_0::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_1(const V1_1::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_1(const V1_2::Capabilities& capabilities) { |
| if ((capabilities.relaxedFloat32toFloat16PerformanceTensor != |
| capabilities.relaxedFloat32toFloat16PerformanceScalar) || |
| (lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_FLOAT32) != |
| lookup(capabilities.operandPerformance, V1_2::OperandType::FLOAT32))) { |
| return false; |
| } |
| |
| return isQuantized8PerformanceConsistentWithP(capabilities); |
| } |
| |
| bool compliantWithV1_1(const V1_3::Capabilities& capabilities) { |
| if ((capabilities.relaxedFloat32toFloat16PerformanceTensor != |
| capabilities.relaxedFloat32toFloat16PerformanceScalar) || |
| (lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32) != |
| lookup(capabilities.operandPerformance, V1_3::OperandType::FLOAT32))) { |
| return false; |
| } |
| |
| return isQuantized8PerformanceConsistentWithP(capabilities); |
| } |
| |
| bool compliantWithV1_2(const V1_0::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_2(const V1_1::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_2(const V1_2::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_2(const V1_3::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_3(const V1_0::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_3(const V1_1::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_3(const V1_2::Capabilities&) { |
| return true; |
| } |
| |
| bool compliantWithV1_3(const V1_3::Capabilities&) { |
| return true; |
| } |
| |
| V1_0::ErrorStatus convertToV1_0(V1_0::ErrorStatus status) { |
| return status; |
| } |
| |
| V1_0::ErrorStatus convertToV1_0(V1_3::ErrorStatus status) { |
| switch (status) { |
| case V1_3::ErrorStatus::NONE: |
| return V1_0::ErrorStatus::NONE; |
| case V1_3::ErrorStatus::DEVICE_UNAVAILABLE: |
| return V1_0::ErrorStatus::DEVICE_UNAVAILABLE; |
| case V1_3::ErrorStatus::GENERAL_FAILURE: |
| return V1_0::ErrorStatus::GENERAL_FAILURE; |
| case V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE: |
| return V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE; |
| case V1_3::ErrorStatus::INVALID_ARGUMENT: |
| return V1_0::ErrorStatus::INVALID_ARGUMENT; |
| case V1_3::ErrorStatus::MISSED_DEADLINE_TRANSIENT: |
| return V1_0::ErrorStatus::GENERAL_FAILURE; |
| case V1_3::ErrorStatus::MISSED_DEADLINE_PERSISTENT: |
| return V1_0::ErrorStatus::GENERAL_FAILURE; |
| case V1_3::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT: |
| return V1_0::ErrorStatus::GENERAL_FAILURE; |
| case V1_3::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT: |
| return V1_0::ErrorStatus::GENERAL_FAILURE; |
| } |
| LOG(ERROR) << "Unknown ErrorStatus: " << toString(status) << " mapped to GENERAL_FAILURE"; |
| return V1_0::ErrorStatus::GENERAL_FAILURE; |
| } |
| |
| V1_3::ErrorStatus convertToV1_3(V1_0::ErrorStatus status) { |
| return static_cast<V1_3::ErrorStatus>(status); |
| } |
| |
| V1_3::ErrorStatus convertToV1_3(V1_3::ErrorStatus status) { |
| return status; |
| } |
| |
| static V1_0::OperationType uncheckedConvertToV1_0(V1_1::OperationType type) { |
| return static_cast<V1_0::OperationType>(type); |
| } |
| |
| static V1_0::OperationType uncheckedConvertToV1_0(V1_2::OperationType type) { |
| return static_cast<V1_0::OperationType>(type); |
| } |
| |
| V1_0::OperationType uncheckedConvertToV1_0(V1_3::OperationType type) { |
| return static_cast<V1_0::OperationType>(type); |
| } |
| |
| static V1_1::OperationType convertToV1_1(V1_0::OperationType type) { |
| return static_cast<V1_1::OperationType>(type); |
| } |
| |
| static V1_1::OperationType uncheckedConvertToV1_1(V1_2::OperationType type) { |
| return static_cast<V1_1::OperationType>(type); |
| } |
| |
| V1_1::OperationType uncheckedConvertToV1_1(V1_3::OperationType type) { |
| return static_cast<V1_1::OperationType>(type); |
| } |
| |
| static V1_2::OperationType convertToV1_2(V1_0::OperationType type) { |
| return static_cast<V1_2::OperationType>(type); |
| } |
| |
| static V1_2::OperationType convertToV1_2(V1_1::OperationType type) { |
| return static_cast<V1_2::OperationType>(type); |
| } |
| |
| V1_2::OperationType uncheckedConvertToV1_2(V1_3::OperationType type) { |
| return static_cast<V1_2::OperationType>(type); |
| } |
| |
| static V1_3::OperationType convertToV1_3(V1_0::OperationType type) { |
| return static_cast<V1_3::OperationType>(type); |
| } |
| |
| static V1_3::OperationType convertToV1_3(V1_1::OperationType type) { |
| return static_cast<V1_3::OperationType>(type); |
| } |
| |
| static V1_3::OperationType convertToV1_3(V1_2::OperationType type) { |
| return static_cast<V1_3::OperationType>(type); |
| } |
| |
| V1_0::Capabilities convertToV1_0(const V1_0::Capabilities& capabilities) { |
| return capabilities; |
| } |
| |
| V1_0::Capabilities convertToV1_0(const V1_1::Capabilities& capabilities) { |
| if (!compliantWithV1_0(capabilities)) { |
| LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities) |
| << " from V1_1::Capabilities to V1_0::Capabilities"; |
| } |
| return {.float32Performance = capabilities.float32Performance, |
| .quantized8Performance = capabilities.quantized8Performance}; |
| } |
| |
| V1_0::Capabilities convertToV1_0(const V1_2::Capabilities& capabilities) { |
| if (!compliantWithV1_0(capabilities)) { |
| LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities) |
| << " from V1_2::Capabilities to V1_0::Capabilities"; |
| } |
| return {.float32Performance = |
| lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_FLOAT32), |
| .quantized8Performance = lookup(capabilities.operandPerformance, |
| V1_2::OperandType::TENSOR_QUANT8_ASYMM)}; |
| } |
| |
| V1_0::Capabilities convertToV1_0(const V1_3::Capabilities& capabilities) { |
| if (!compliantWithV1_0(capabilities)) { |
| LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities) |
| << " from V1_3::Capabilities to V1_0::Capabilities"; |
| } |
| return {.float32Performance = |
| lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32), |
| .quantized8Performance = lookup(capabilities.operandPerformance, |
| V1_3::OperandType::TENSOR_QUANT8_ASYMM)}; |
| } |
| |
| V1_1::Capabilities convertToV1_1(const V1_0::Capabilities& capabilities) { |
| return {.float32Performance = capabilities.float32Performance, |
| .quantized8Performance = capabilities.quantized8Performance, |
| .relaxedFloat32toFloat16Performance = capabilities.float32Performance}; |
| } |
| |
| V1_1::Capabilities convertToV1_1(const V1_1::Capabilities& capabilities) { |
| return capabilities; |
| } |
| |
| V1_1::Capabilities convertToV1_1(const V1_2::Capabilities& capabilities) { |
| if (!compliantWithV1_1(capabilities)) { |
| LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities) |
| << " from V1_2::Capabilities to V1_1::Capabilities"; |
| } |
| return {.float32Performance = |
| lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_FLOAT32), |
| .quantized8Performance = |
| lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_QUANT8_ASYMM), |
| .relaxedFloat32toFloat16Performance = |
| capabilities.relaxedFloat32toFloat16PerformanceTensor}; |
| } |
| |
| V1_1::Capabilities convertToV1_1(const V1_3::Capabilities& capabilities) { |
| if (!compliantWithV1_1(capabilities)) { |
| LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities) |
| << " from V1_3::Capabilities to V1_1::Capabilities"; |
| } |
| return {.float32Performance = |
| lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32), |
| .quantized8Performance = |
| lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM), |
| .relaxedFloat32toFloat16Performance = |
| capabilities.relaxedFloat32toFloat16PerformanceTensor}; |
| } |
| |
| V1_2::Capabilities convertToV1_2(const V1_0::Capabilities& capabilities) { |
| V1_2::Capabilities ret = { |
| .relaxedFloat32toFloat16PerformanceScalar = capabilities.float32Performance, |
| .relaxedFloat32toFloat16PerformanceTensor = capabilities.float32Performance, |
| .operandPerformance = |
| makeQuantized8PerformanceConsistentWithP(capabilities.quantized8Performance)}; |
| auto& opPerf = ret.operandPerformance; |
| opPerf.resize(opPerf.size() + 2); |
| opPerf[opPerf.size() - 2] = {V1_2::OperandType::TENSOR_FLOAT32, |
| capabilities.float32Performance}; |
| opPerf[opPerf.size() - 1] = {V1_2::OperandType::FLOAT32, capabilities.float32Performance}; |
| using OperandPerformance = V1_2::Capabilities::OperandPerformance; |
| std::sort(opPerf.begin(), opPerf.end(), |
| [](const OperandPerformance& a, const OperandPerformance& b) { |
| return a.type < b.type; |
| }); |
| return ret; |
| } |
| |
| V1_2::Capabilities convertToV1_2(const V1_1::Capabilities& capabilities) { |
| V1_2::Capabilities ret = {.relaxedFloat32toFloat16PerformanceScalar = |
| capabilities.relaxedFloat32toFloat16Performance, |
| .relaxedFloat32toFloat16PerformanceTensor = |
| capabilities.relaxedFloat32toFloat16Performance, |
| .operandPerformance = makeQuantized8PerformanceConsistentWithP( |
| capabilities.quantized8Performance)}; |
| auto& opPerf = ret.operandPerformance; |
| opPerf.resize(opPerf.size() + 2); |
| opPerf[opPerf.size() - 2] = {V1_2::OperandType::TENSOR_FLOAT32, |
| capabilities.float32Performance}; |
| opPerf[opPerf.size() - 1] = {V1_2::OperandType::FLOAT32, capabilities.float32Performance}; |
| using OperandPerformance = V1_2::Capabilities::OperandPerformance; |
| std::sort(opPerf.begin(), opPerf.end(), |
| [](const OperandPerformance& a, const OperandPerformance& b) { |
| return a.type < b.type; |
| }); |
| return ret; |
| } |
| |
| V1_2::Capabilities convertToV1_2(const V1_2::Capabilities& capabilities) { |
| return capabilities; |
| } |
| |
| V1_2::Capabilities convertToV1_2(const V1_3::Capabilities& capabilities) { |
| V1_2::Capabilities ret = { |
| .relaxedFloat32toFloat16PerformanceScalar = |
| capabilities.relaxedFloat32toFloat16PerformanceScalar, |
| .relaxedFloat32toFloat16PerformanceTensor = |
| capabilities.relaxedFloat32toFloat16PerformanceTensor, |
| }; |
| const auto& inputOpPerf = capabilities.operandPerformance; |
| hardware::hidl_vec<V1_3::Capabilities::OperandPerformance> opPerfSupported; |
| opPerfSupported.resize(inputOpPerf.size()); |
| auto last = |
| std::copy_if(inputOpPerf.begin(), inputOpPerf.end(), opPerfSupported.begin(), |
| [](V1_3::Capabilities::OperandPerformance opPerf) { |
| return validOperandType(static_cast<V1_2::OperandType>(opPerf.type)); |
| }); |
| opPerfSupported.resize(std::distance(opPerfSupported.begin(), last)); |
| |
| auto& convertedOpPerf = ret.operandPerformance; |
| convertedOpPerf.resize(opPerfSupported.size()); |
| std::transform(opPerfSupported.begin(), opPerfSupported.end(), convertedOpPerf.begin(), |
| [](V1_3::Capabilities::OperandPerformance opPerf) { |
| return V1_2::Capabilities::OperandPerformance{ |
| static_cast<V1_2::OperandType>(opPerf.type), opPerf.info}; |
| }); |
| return ret; |
| } |
| |
| V1_3::Capabilities convertToV1_3(const V1_0::Capabilities& capabilities) { |
| return convertToV1_3(convertToV1_2(capabilities)); |
| } |
| |
| V1_3::Capabilities convertToV1_3(const V1_1::Capabilities& capabilities) { |
| return convertToV1_3(convertToV1_2(capabilities)); |
| } |
| |
| V1_3::Capabilities convertToV1_3(const V1_2::Capabilities& capabilities) { |
| V1_3::Capabilities ret = { |
| .relaxedFloat32toFloat16PerformanceScalar = |
| capabilities.relaxedFloat32toFloat16PerformanceScalar, |
| .relaxedFloat32toFloat16PerformanceTensor = |
| capabilities.relaxedFloat32toFloat16PerformanceTensor, |
| .ifPerformance = kNoPerformanceInfo, |
| .whilePerformance = kNoPerformanceInfo, |
| }; |
| auto& opPerf = ret.operandPerformance; |
| opPerf.resize(capabilities.operandPerformance.size()); |
| std::transform(capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(), |
| opPerf.begin(), [](V1_2::Capabilities::OperandPerformance opPerf) { |
| return V1_3::Capabilities::OperandPerformance{ |
| static_cast<V1_3::OperandType>(opPerf.type), opPerf.info}; |
| }); |
| return ret; |
| } |
| |
| V1_3::Capabilities convertToV1_3(const V1_3::Capabilities& capabilities) { |
| return capabilities; |
| } |
| |
| static V1_0::Operation uncheckedConvertToV1_0(const V1_1::Operation& operation) { |
| return {.type = uncheckedConvertToV1_0(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_1::Operation convertToV1_1(const V1_0::Operation& operation) { |
| return {.type = convertToV1_1(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static hardware::hidl_vec<V1_0::Operation> uncheckedConvertToV1_0( |
| const hardware::hidl_vec<V1_1::Operation>& operations) { |
| hardware::hidl_vec<V1_0::Operation> result(operations.size()); |
| std::transform( |
| operations.begin(), operations.end(), result.begin(), |
| [](const V1_1::Operation& operation) { return uncheckedConvertToV1_0(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_1::Operation> convertToV1_1( |
| const hardware::hidl_vec<V1_0::Operation>& operations) { |
| hardware::hidl_vec<V1_1::Operation> result(operations.size()); |
| std::transform(operations.begin(), operations.end(), result.begin(), |
| [](const V1_0::Operation& operation) { return convertToV1_1(operation); }); |
| return result; |
| } |
| |
| bool compliantWithV1_0(const V1_3::Operand& operand) { |
| return validOperandType(static_cast<V1_0::OperandType>(operand.type)) && |
| (nonExtensionOperandTypeIsScalar(static_cast<int>(operand.type)) || |
| operand.dimensions.size() != 0) && |
| compliantWithV1_0(operand.lifetime); |
| } |
| |
| bool compliantWithV1_2(const V1_3::Operand& operand) { |
| return validOperandType(static_cast<V1_2::OperandType>(operand.type)) && |
| compliantWithV1_0(operand.lifetime); |
| } |
| |
| bool compliantWithV1_3(const V1_3::Operand& /*operand*/) { |
| return true; |
| } |
| |
| bool compliantWithAidl(const V1_3::Operand& operand) { |
| if (static_cast<std::underlying_type_t<V1_3::OperandType>>(operand.type) > |
| std::numeric_limits<int32_t>::max()) { |
| return false; |
| } |
| if (operand.location.poolIndex > std::numeric_limits<int32_t>::max()) { |
| return false; |
| } |
| if (operand.extraParams.getDiscriminator() == |
| V1_2::Operand::ExtraParams::hidl_discriminator::channelQuant && |
| operand.extraParams.channelQuant().channelDim > std::numeric_limits<int32_t>::max()) { |
| return false; |
| } |
| for (auto dim : operand.dimensions) { |
| if (dim > std::numeric_limits<int32_t>::max()) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| static bool compliantWith(HalVersion version, const V1_3::Model& model, |
| std::set<uint32_t>* noncompliantOperations) { |
| // A boolean vector indicating whether each pool is compliant with the target HAL version. |
| std::vector<bool> isPoolCompliant(model.pools.size(), false); |
| std::transform( |
| model.pools.begin(), model.pools.end(), isPoolCompliant.begin(), |
| [version](const hardware::hidl_memory& pool) { return validatePool(pool, version); }); |
| |
| // A boolean vector indicating whether each operand is compliant with the target HAL version. |
| std::vector<bool> isOperandCompliant(model.main.operands.size(), false); |
| std::transform(model.main.operands.begin(), model.main.operands.end(), |
| isOperandCompliant.begin(), |
| [&isPoolCompliant, version](const V1_3::Operand& op) { |
| bool is_operand_compliant = false; |
| switch (version) { |
| case HalVersion::UNKNOWN: |
| is_operand_compliant = false; |
| break; |
| case HalVersion::V1_0: |
| is_operand_compliant = compliantWithV1_0(op); |
| break; |
| case HalVersion::V1_1: |
| // There is no V1_1::Operand -- both V1_0::Model |
| // and V1_1::Model use V1_0::Operand. |
| is_operand_compliant = compliantWithV1_0(op); |
| break; |
| case HalVersion::V1_2: |
| is_operand_compliant = compliantWithV1_2(op); |
| break; |
| case HalVersion::V1_3: |
| is_operand_compliant = compliantWithV1_3(op); |
| break; |
| case HalVersion::AIDL_UNSTABLE: |
| is_operand_compliant = compliantWithAidl(op); |
| break; |
| } |
| return is_operand_compliant && |
| !(op.lifetime == V1_3::OperandLifeTime::CONSTANT_REFERENCE && |
| !isPoolCompliant[op.location.poolIndex]); |
| }); |
| |
| auto allOperandsCompliant = [&isOperandCompliant](const hardware::hidl_vec<uint32_t>& indices) { |
| return std::all_of( |
| indices.begin(), indices.end(), |
| [&isOperandCompliant](const uint32_t ind) { return isOperandCompliant[ind]; }); |
| }; |
| |
| auto localValidateOperation = [&model, version, |
| &allOperandsCompliant](const V1_3::Operation& op) { |
| if (!allOperandsCompliant(op.inputs) || !allOperandsCompliant(op.outputs)) return false; |
| int error = validateOperation(static_cast<int32_t>(op.type), op.inputs.size(), |
| op.inputs.size() > 0 ? op.inputs.data() : nullptr, |
| op.outputs.size(), |
| op.outputs.size() > 0 ? op.outputs.data() : nullptr, |
| uncheckedConvert(model.main.operands), version); |
| return error == ANEURALNETWORKS_NO_ERROR; |
| }; |
| |
| if (noncompliantOperations) { |
| CHECK(noncompliantOperations->empty()); |
| for (uint32_t idx = 0; idx < model.main.operations.size(); ++idx) { |
| if (!localValidateOperation(model.main.operations[idx])) { |
| noncompliantOperations->insert(idx); |
| } |
| } |
| return noncompliantOperations->empty(); |
| } else { |
| return std::all_of(model.main.operations.begin(), model.main.operations.end(), |
| localValidateOperation); |
| } |
| } |
| |
| bool compliantWithV1_0(const V1_0::Model& /*model*/) { |
| return true; |
| } |
| |
| bool compliantWithV1_0(const V1_1::Model& model) { |
| // In addition to new enumeration values being introduced in V1_1::Model, a |
| // new flag was introduced to indicate whether or not float32 data can be |
| // calculated using float16 units. This 'relaxComputationFloat32toFloat16' |
| // flag is not relevant in whether a V1_1::Model is compliant with a |
| // V1_0::Model because all 1.0 drivers require strict calculation by default |
| // in the P NN runtime. Even if fp16 calculations are allowed, they can |
| // still be computed by a strict fp32 driver. |
| auto operands = uncheckedConvert(convertToV1_3(model.operands)); |
| return std::all_of(model.operations.begin(), model.operations.end(), |
| [&operands](const V1_1::Operation& op) { |
| int error = validateOperation( |
| static_cast<int32_t>(op.type), op.inputs.size(), |
| op.inputs.size() > 0 ? op.inputs.data() : nullptr, |
| op.outputs.size(), |
| op.outputs.size() > 0 ? op.outputs.data() : nullptr, operands, |
| HalVersion::V1_0); |
| return error == ANEURALNETWORKS_NO_ERROR; |
| }); |
| } |
| |
| bool compliantWithV1_0(const V1_2::Model& model, std::set<uint32_t>* noncompliantOperations) { |
| return compliantWith(HalVersion::V1_0, convertToV1_3(model), noncompliantOperations); |
| } |
| |
| bool compliantWithV1_0(const V1_3::Model& model, std::set<uint32_t>* noncompliantOperations) { |
| return compliantWith(HalVersion::V1_0, model, noncompliantOperations); |
| } |
| |
| bool compliantWithV1_1(const V1_0::Model&) { |
| return true; |
| } |
| |
| bool compliantWithV1_1(const V1_1::Model&) { |
| return true; |
| } |
| |
| bool compliantWithV1_1(const V1_2::Model& model, std::set<uint32_t>* noncompliantOperations) { |
| return compliantWith(HalVersion::V1_1, convertToV1_3(model), noncompliantOperations); |
| } |
| |
| bool compliantWithV1_1(const V1_3::Model& model, std::set<uint32_t>* noncompliantOperations) { |
| return compliantWith(HalVersion::V1_1, model, noncompliantOperations); |
| } |
| |
| bool compliantWithV1_2(const V1_0::Model&) { |
| return true; |
| } |
| |
| bool compliantWithV1_2(const V1_1::Model&) { |
| return true; |
| } |
| |
| bool compliantWithV1_2(const V1_2::Model&, std::set<uint32_t>* /*noncompliantOperations*/) { |
| return true; |
| } |
| |
| bool compliantWithV1_2(const V1_3::Model& model, std::set<uint32_t>* noncompliantOperations) { |
| return compliantWith(HalVersion::V1_2, model, noncompliantOperations); |
| } |
| |
| static V1_0::Operation uncheckedConvertToV1_0(const V1_2::Operation& operation) { |
| return {.type = uncheckedConvertToV1_0(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_0::Operation uncheckedConvertToV1_0(const V1_3::Operation& operation) { |
| return {.type = uncheckedConvertToV1_0(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_1::Operation uncheckedConvertToV1_1(const V1_2::Operation& operation) { |
| return {.type = uncheckedConvertToV1_1(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_1::Operation uncheckedConvertToV1_1(const V1_3::Operation& operation) { |
| return {.type = uncheckedConvertToV1_1(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_2::Operation convertToV1_2(const V1_0::Operation& operation) { |
| return {.type = convertToV1_2(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_2::Operation convertToV1_2(const V1_1::Operation& operation) { |
| return {.type = convertToV1_2(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_2::Operation uncheckedConvertToV1_2(const V1_3::Operation& operation) { |
| return {.type = uncheckedConvertToV1_2(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_3::Operation convertToV1_3(const V1_0::Operation& operation) { |
| return {.type = convertToV1_3(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_3::Operation convertToV1_3(const V1_1::Operation& operation) { |
| return {.type = convertToV1_3(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static V1_3::Operation convertToV1_3(const V1_2::Operation& operation) { |
| return {.type = convertToV1_3(operation.type), |
| .inputs = operation.inputs, |
| .outputs = operation.outputs}; |
| } |
| |
| static hardware::hidl_vec<V1_0::Operation> uncheckedConvertToV1_0( |
| const hardware::hidl_vec<V1_3::Operation>& operations) { |
| hardware::hidl_vec<V1_0::Operation> result(operations.size()); |
| std::transform( |
| operations.begin(), operations.end(), result.begin(), |
| [](const V1_3::Operation& operation) { return uncheckedConvertToV1_0(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_0::Operation> uncheckedConvertToV1_0( |
| const hardware::hidl_vec<V1_2::Operation>& operations) { |
| hardware::hidl_vec<V1_0::Operation> result(operations.size()); |
| std::transform( |
| operations.begin(), operations.end(), result.begin(), |
| [](const V1_2::Operation& operation) { return uncheckedConvertToV1_0(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_2::Operation> uncheckedConvertToV1_2( |
| const hardware::hidl_vec<V1_3::Operation>& operations) { |
| hardware::hidl_vec<V1_2::Operation> result(operations.size()); |
| std::transform( |
| operations.begin(), operations.end(), result.begin(), |
| [](const V1_3::Operation& operation) { return uncheckedConvertToV1_2(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_1::Operation> uncheckedConvertToV1_1( |
| const hardware::hidl_vec<V1_2::Operation>& operations) { |
| hardware::hidl_vec<V1_1::Operation> result(operations.size()); |
| std::transform( |
| operations.begin(), operations.end(), result.begin(), |
| [](const V1_2::Operation& operation) { return uncheckedConvertToV1_1(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_1::Operation> uncheckedConvertToV1_1( |
| const hardware::hidl_vec<V1_3::Operation>& operations) { |
| hardware::hidl_vec<V1_1::Operation> result(operations.size()); |
| std::transform( |
| operations.begin(), operations.end(), result.begin(), |
| [](const V1_3::Operation& operation) { return uncheckedConvertToV1_1(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_2::Operation> convertToV1_2( |
| const hardware::hidl_vec<V1_0::Operation>& operations) { |
| hardware::hidl_vec<V1_2::Operation> result(operations.size()); |
| std::transform(operations.begin(), operations.end(), result.begin(), |
| [](const V1_0::Operation& operation) { return convertToV1_2(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_2::Operation> convertToV1_2( |
| const hardware::hidl_vec<V1_1::Operation>& operations) { |
| hardware::hidl_vec<V1_2::Operation> result(operations.size()); |
| std::transform(operations.begin(), operations.end(), result.begin(), |
| [](const V1_1::Operation& operation) { return convertToV1_2(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_3::Operation> convertToV1_3( |
| const hardware::hidl_vec<V1_0::Operation>& operations) { |
| hardware::hidl_vec<V1_3::Operation> result(operations.size()); |
| std::transform(operations.begin(), operations.end(), result.begin(), |
| [](const V1_0::Operation& operation) { return convertToV1_3(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_3::Operation> convertToV1_3( |
| const hardware::hidl_vec<V1_1::Operation>& operations) { |
| hardware::hidl_vec<V1_3::Operation> result(operations.size()); |
| std::transform(operations.begin(), operations.end(), result.begin(), |
| [](const V1_1::Operation& operation) { return convertToV1_3(operation); }); |
| return result; |
| } |
| |
| static hardware::hidl_vec<V1_3::Operation> convertToV1_3( |
| const hardware::hidl_vec<V1_2::Operation>& operations) { |
| hardware::hidl_vec<V1_3::Operation> result(operations.size()); |
| std::transform(operations.begin(), operations.end(), result.begin(), |
| [](const V1_2::Operation& operation) { return convertToV1_3(operation); }); |
| return result; |
| } |
| |
| static bool compliantWithV1_0(const V1_2::OperandType& operandType) { |
| return validOperandType(static_cast<V1_0::OperandType>(operandType)); |
| } |
| |
| static bool compliantWithV1_0(const V1_3::OperandType& operandType) { |
| return validOperandType(static_cast<V1_0::OperandType>(operandType)); |
| } |
| |
| static bool compliantWithV1_2(const V1_3::OperandType& operandType) { |
| return validOperandType(static_cast<V1_2::OperandType>(operandType)); |
| } |
| |
| V1_0::OperandType convertToV1_0(const V1_2::OperandType& operandType) { |
| if (!compliantWithV1_0(operandType)) { |
| LOG(ERROR) << "Upcasting non-compliant operand type " << toString(operandType) |
| << " from V1_2::OperandType to V1_0::OperandType"; |
| } |
| return static_cast<V1_0::OperandType>(operandType); |
| } |
| |
| V1_2::OperandType convertToV1_2(const V1_0::OperandType& operandType) { |
| return static_cast<V1_2::OperandType>(operandType); |
| } |
| |
| V1_2::OperandType convertToV1_2(const V1_3::OperandType& operandType) { |
| if (!compliantWithV1_2(operandType)) { |
| LOG(ERROR) << "Upcasting non-compliant operand type " << toString(operandType) |
| << " from V1_3::OperandType to V1_2::OperandType"; |
| } |
| return static_cast<V1_2::OperandType>(operandType); |
| } |
| |
| V1_0::OperandType convertToV1_0(const V1_3::OperandType& operandType) { |
| if (!compliantWithV1_0(operandType)) { |
| LOG(ERROR) << "Upcasting non-compliant operand type " << toString(operandType) |
| << " from V1_3::Operand to V1_0::Operand"; |
| } |
| return static_cast<V1_0::OperandType>(operandType); |
| } |
| |
| bool compliantWithV1_0(V1_0::OperandLifeTime /*lifetime*/) { |
| return true; |
| } |
| |
| bool compliantWithV1_0(V1_3::OperandLifeTime lifetime) { |
| return lifetime != V1_3::OperandLifeTime::SUBGRAPH; |
| } |
| |
| bool compliantWithV1_3(V1_0::OperandLifeTime /*lifetime*/) { |
| return true; |
| } |
| |
| bool compliantWithV1_3(V1_3::OperandLifeTime /*lifetime*/) { |
| return true; |
| } |
| |
| V1_0::OperandLifeTime convertToV1_0(V1_0::OperandLifeTime lifetime) { |
| return lifetime; |
| } |
| |
| V1_0::OperandLifeTime convertToV1_0(V1_3::OperandLifeTime lifetime) { |
| if (!compliantWithV1_0(lifetime)) { |
| LOG(ERROR) << "Upcasting non-compliant lifetime " << toString(lifetime) |
| << " from V1_3 to V1_0"; |
| } |
| return static_cast<V1_0::OperandLifeTime>(lifetime); |
| } |
| |
| V1_3::OperandLifeTime convertToV1_3(V1_0::OperandLifeTime lifetime) { |
| return static_cast<V1_3::OperandLifeTime>(lifetime); |
| } |
| |
| V1_3::OperandLifeTime convertToV1_3(V1_3::OperandLifeTime lifetime) { |
| return lifetime; |
| } |
| |
| V1_0::Operand convertToV1_0(const V1_2::Operand& operand) { |
| return {.type = convertToV1_0(operand.type), |
| .dimensions = operand.dimensions, |
| .numberOfConsumers = operand.numberOfConsumers, |
| .scale = operand.scale, |
| .zeroPoint = operand.zeroPoint, |
| .lifetime = convertToV1_0(operand.lifetime), |
| .location = operand.location}; |
| } |
| |
| V1_0::Operand convertToV1_0(const V1_3::Operand& operand) { |
| return {.type = convertToV1_0(operand.type), |
| .dimensions = operand.dimensions, |
| .numberOfConsumers = operand.numberOfConsumers, |
| .scale = operand.scale, |
| .zeroPoint = operand.zeroPoint, |
| .lifetime = convertToV1_0(operand.lifetime), |
| .location = operand.location}; |
| } |
| |
| V1_2::Operand convertToV1_2(const V1_0::Operand& operand) { |
| return {.type = convertToV1_2(operand.type), |
| .dimensions = operand.dimensions, |
| .numberOfConsumers = operand.numberOfConsumers, |
| .scale = operand.scale, |
| .zeroPoint = operand.zeroPoint, |
| .lifetime = operand.lifetime, |
| .location = operand.location}; |
| } |
| |
| V1_2::Operand convertToV1_2(const V1_3::Operand& operand) { |
| return {.type = convertToV1_2(operand.type), |
| .dimensions = operand.dimensions, |
| .numberOfConsumers = operand.numberOfConsumers, |
| .scale = operand.scale, |
| .zeroPoint = operand.zeroPoint, |
| .lifetime = static_cast<V1_0::OperandLifeTime>(operand.lifetime), |
| .location = operand.location, |
| .extraParams = operand.extraParams}; |
| } |
| |
| V1_3::Operand convertToV1_3(const V1_0::Operand& operand) { |
| return {.type = static_cast<V1_3::OperandType>(operand.type), |
| .dimensions = operand.dimensions, |
| .numberOfConsumers = operand.numberOfConsumers, |
| .scale = operand.scale, |
| .zeroPoint = operand.zeroPoint, |
| .lifetime = convertToV1_3(operand.lifetime), |
| .location = operand.location}; |
| } |
| |
| V1_3::Operand convertToV1_3(const V1_2::Operand& operand) { |
| return {.type = static_cast<V1_3::OperandType>(operand.type), |
| .dimensions = operand.dimensions, |
| .numberOfConsumers = operand.numberOfConsumers, |
| .scale = operand.scale, |
| .zeroPoint = operand.zeroPoint, |
| .lifetime = convertToV1_3(operand.lifetime), |
| .location = operand.location, |
| .extraParams = operand.extraParams}; |
| } |
| |
| V1_3::Operand convertToV1_3(const V1_3::Operand& operand) { |
| return operand; |
| } |
| |
| hardware::hidl_vec<V1_0::Operand> convertToV1_0(const hardware::hidl_vec<V1_0::Operand>& operands) { |
| return operands; |
| } |
| |
| hardware::hidl_vec<V1_0::Operand> convertToV1_0(const hardware::hidl_vec<V1_2::Operand>& operands) { |
| hardware::hidl_vec<V1_0::Operand> result(operands.size()); |
| std::transform(operands.begin(), operands.end(), result.begin(), |
| [](const V1_2::Operand& operand) { return convertToV1_0(operand); }); |
| return result; |
| } |
| |
| hardware::hidl_vec<V1_0::Operand> convertToV1_0(const hardware::hidl_vec<V1_3::Operand>& operands) { |
| hardware::hidl_vec<V1_0::Operand> result(operands.size()); |
| std::transform(operands.begin(), operands.end(), result.begin(), |
| [](const V1_3::Operand& operand) { return convertToV1_0(operand); }); |
| return result; |
| } |
| |
| hardware::hidl_vec<V1_2::Operand> convertToV1_2(const hardware::hidl_vec<V1_0::Operand>& operands) { |
| hardware::hidl_vec<V1_2::Operand> result(operands.size()); |
| std::transform(operands.begin(), operands.end(), result.begin(), |
| [](const V1_0::Operand& operand) { return convertToV1_2(operand); }); |
| return result; |
| } |
| |
| hardware::hidl_vec<V1_2::Operand> convertToV1_2(const hardware::hidl_vec<V1_2::Operand>& operands) { |
| return operands; |
| } |
| |
| hardware::hidl_vec<V1_2::Operand> convertToV1_2(const hardware::hidl_vec<V1_3::Operand>& operands) { |
| hardware::hidl_vec<V1_2::Operand> result(operands.size()); |
| std::transform(operands.begin(), operands.end(), result.begin(), |
| [](const V1_3::Operand& operand) { return convertToV1_2(operand); }); |
| return result; |
| } |
| |
| hardware::hidl_vec<V1_3::Operand> convertToV1_3(const hardware::hidl_vec<V1_0::Operand>& operands) { |
| hardware::hidl_vec<V1_3::Operand> result(operands.size()); |
| std::transform(operands.begin(), operands.end(), result.begin(), |
| [](const V1_0::Operand& operand) { return convertToV1_3(operand); }); |
| return result; |
| } |
| |
| hardware::hidl_vec<V1_3::Operand> convertToV1_3(const hardware::hidl_vec<V1_2::Operand>& operands) { |
| hardware::hidl_vec<V1_3::Operand> result(operands.size()); |
| std::transform(operands.begin(), operands.end(), result.begin(), |
| [](const V1_2::Operand& operand) { return convertToV1_3(operand); }); |
| return result; |
| } |
| |
| hardware::hidl_vec<V1_3::Operand> convertToV1_3(const hardware::hidl_vec<V1_3::Operand>& operands) { |
| return operands; |
| } |
| |
| V1_0::Model convertToV1_0(const V1_0::Model& model) { |
| return model; |
| } |
| |
| V1_0::Model convertToV1_0(const V1_1::Model& model) { |
| if (!compliantWithV1_0(model)) { |
| LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model)) |
| << " from V1_1::Model to V1_0::Model"; |
| } |
| return {.operands = model.operands, |
| .operations = uncheckedConvertToV1_0(model.operations), |
| .inputIndexes = model.inputIndexes, |
| .outputIndexes = model.outputIndexes, |
| .operandValues = model.operandValues, |
| .pools = model.pools}; |
| } |
| |
| V1_0::Model convertToV1_0(const V1_2::Model& model) { |
| if (!compliantWithV1_0(model)) { |
| LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model)) |
| << " from V1_2::Model to V1_0::Model"; |
| } |
| return {.operands = convertToV1_0(model.operands), |
| .operations = uncheckedConvertToV1_0(model.operations), |
| .inputIndexes = model.inputIndexes, |
| .outputIndexes = model.outputIndexes, |
| .operandValues = model.operandValues, |
| .pools = model.pools}; |
| } |
| |
| V1_0::Model convertToV1_0(const V1_3::Model& model) { |
| if (!compliantWithV1_0(model)) { |
| LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model)) |
| << " from V1_3::Model to V1_0::Model"; |
| } |
| return {.operands = convertToV1_0(model.main.operands), |
| .operations = uncheckedConvertToV1_0(model.main.operations), |
| .inputIndexes = model.main.inputIndexes, |
| .outputIndexes = model.main.outputIndexes, |
| .operandValues = model.operandValues, |
| .pools = model.pools}; |
| } |
| |
| V1_1::Model convertToV1_1(const V1_0::Model& model) { |
| return {.operands = model.operands, |
| .operations = convertToV1_1(model.operations), |
| .inputIndexes = model.inputIndexes, |
| .outputIndexes = model.outputIndexes, |
| .operandValues = model.operandValues, |
| .pools = model.pools, |
| .relaxComputationFloat32toFloat16 = false}; |
| } |
| |
| V1_1::Model convertToV1_1(const V1_1::Model& model) { |
| return model; |
| } |
| |
| V1_1::Model convertToV1_1(const V1_2::Model& model) { |
| if (!compliantWithV1_1(model)) { |
| LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model)) |
| << " from V1_2::Model to V1_1::Model"; |
| } |
| return {.operands = convertToV1_0(model.operands), // Operands in 1.1 and 1.0 are identical. |
| .operations = uncheckedConvertToV1_1(model.operations), |
| .inputIndexes = model.inputIndexes, |
| .outputIndexes = model.outputIndexes, |
| .operandValues = model.operandValues, |
| .pools = model.pools, |
| .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16}; |
| } |
| |
| V1_1::Model convertToV1_1(const V1_3::Model& model) { |
| if (!compliantWithV1_1(model)) { |
| LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model)) |
| << " from V1_3::Model to V1_1::Model"; |
| } |
| return {// Operands in 1.1 and 1.0 are identical. |
| .operands = convertToV1_0(model.main.operands), |
| .operations = uncheckedConvertToV1_1(model.main.operations), |
| .inputIndexes = model.main.inputIndexes, |
| .outputIndexes = model.main.outputIndexes, |
| .operandValues = model.operandValues, |
| .pools = model.pools, |
| .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16}; |
| } |
| |
| V1_2::Model convertToV1_2(const V1_0::Model& model) { |
| return {.operands = convertToV1_2(model.operands), |
| .operations = convertToV1_2(model.operations), |
| .inputIndexes = model.inputIndexes, |
| .outputIndexes = model.outputIndexes, |
| .operandValues = model.operandValues, |
| .pools = model.pools, |
| .relaxComputationFloat32toFloat16 = false}; |
| } |
| |
| V1_2::Model convertToV1_2(const V1_1::Model& model) { |
| return {.operands = convertToV1_2(model.operands), |
| .operations = convertToV1_2(model.operations), |
| .inputIndexes = model.inputIndexes, |
| .outputIndexes = model.outputIndexes, |
| .operandValues = model.operandValues, |
| .pools = model.pools, |
| .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16}; |
| } |
| |
| V1_2::Model convertToV1_2(const V1_2::Model& model) { |
| return model; |
| } |
| |
| V1_2::Model convertToV1_2(const V1_3::Model& model) { |
| if (!compliantWithV1_2(model)) { |
| LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model)) |
| << " from V1_3::Model to V1_2::Model"; |
| } |
| return {.operands = convertToV1_2(model.main.operands), |
| .operations = uncheckedConvertToV1_2(model.main.operations), |
| .inputIndexes = model.main.inputIndexes, |
| .outputIndexes = model.main.outputIndexes, |
| .operandValues = model.operandValues, |
| .pools = model.pools, |
| .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16, |
| .extensionNameToPrefix = model.extensionNameToPrefix}; |
| } |
| |
| V1_3::Model convertToV1_3(const V1_0::Model& model) { |
| return {.main = {.operands = convertToV1_3(model.operands), |
| .operations = convertToV1_3(model.operations), |
| .inputIndexes = model.inputIndexes, |
| .outputIndexes = model.outputIndexes}, |
| .operandValues = model.operandValues, |
| .pools = model.pools, |
| .relaxComputationFloat32toFloat16 = false}; |
| } |
| |
| V1_3::Model convertToV1_3(const V1_1::Model& model) { |
| return {.main = {.operands = convertToV1_3(model.operands), |
| .operations = convertToV1_3(model.operations), |
| .inputIndexes = model.inputIndexes, |
| .outputIndexes = model.outputIndexes}, |
| .operandValues = model.operandValues, |
| .pools = model.pools, |
| .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16}; |
| } |
| |
| V1_3::Model convertToV1_3(const V1_2::Model& model) { |
| return {.main = {.operands = convertToV1_3(model.operands), |
| .operations = convertToV1_3(model.operations), |
| .inputIndexes = model.inputIndexes, |
| .outputIndexes = model.outputIndexes}, |
| .operandValues = model.operandValues, |
| .pools = model.pools, |
| .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16, |
| .extensionNameToPrefix = model.extensionNameToPrefix}; |
| } |
| |
| V1_3::Model convertToV1_3(const V1_3::Model& model) { |
| return model; |
| } |
| |
| bool compliantWithV1_0(const V1_0::Request& /*request*/) { |
| return true; |
| } |
| |
| bool compliantWithV1_0(const V1_3::Request& request) { |
| return std::all_of(request.pools.begin(), request.pools.end(), [](const auto& pool) { |
| if (pool.getDiscriminator() != V1_3::Request::MemoryPool::hidl_discriminator::hidlMemory) { |
| return false; |
| } |
| const auto& name = pool.hidlMemory().name(); |
| return name == "ashmem" || name == "mmap_fd"; |
| }); |
| } |
| |
| bool compliantWithV1_2(const V1_3::Request& request) { |
| return std::all_of(request.pools.begin(), request.pools.end(), [](const auto& pool) { |
| if (pool.getDiscriminator() != V1_3::Request::MemoryPool::hidl_discriminator::hidlMemory) { |
| return false; |
| } |
| const auto& name = pool.hidlMemory().name(); |
| return name == "ashmem" || name == "mmap_fd" || name == "hardware_buffer_blob" || |
| name == "hardware_buffer"; |
| }); |
| } |
| |
| static hardware::hidl_memory convertToV1_0(const V1_3::Request::MemoryPool& pool) { |
| switch (pool.getDiscriminator()) { |
| case V1_3::Request::MemoryPool::hidl_discriminator::hidlMemory: |
| return pool.hidlMemory(); |
| case V1_3::Request::MemoryPool::hidl_discriminator::token: |
| return hardware::hidl_memory{}; |
| } |
| } |
| |
| static V1_3::Request::MemoryPool convertToV1_3(const hardware::hidl_memory& pool) { |
| V1_3::Request::MemoryPool ret; |
| ret.hidlMemory(pool); |
| return ret; |
| } |
| |
| V1_0::Request convertToV1_0(const V1_0::Request& request) { |
| return request; |
| } |
| |
| static V1_0::Request uncheckedConvertToV1_0(const V1_3::Request& request) { |
| hardware::hidl_vec<hardware::hidl_memory> pools(request.pools.size()); |
| std::transform(request.pools.begin(), request.pools.end(), pools.begin(), |
| [](const auto& pool) { return convertToV1_0(pool); }); |
| return {.inputs = request.inputs, .outputs = request.outputs, .pools = std::move(pools)}; |
| } |
| |
| V1_0::Request convertToV1_0(const V1_3::Request& request) { |
| if (!compliantWithV1_0(request)) { |
| LOG(ERROR) << "Upcasting non-compliant request " << SHOW_IF_DEBUG(toString(request)) |
| << " from V1_3::Request to V1_0::Request of version 1.0"; |
| } |
| return uncheckedConvertToV1_0(request); |
| } |
| |
| V1_0::Request convertToV1_2(const V1_3::Request& request) { |
| if (!compliantWithV1_2(request)) { |
| LOG(ERROR) << "Upcasting non-compliant request " << SHOW_IF_DEBUG(toString(request)) |
| << " from V1_3::Request to V1_0::Request of version 1.2"; |
| } |
| return uncheckedConvertToV1_0(request); |
| } |
| |
| V1_3::Request convertToV1_3(const V1_0::Request& request) { |
| hardware::hidl_vec<V1_3::Request::MemoryPool> pools(request.pools.size()); |
| std::transform(request.pools.begin(), request.pools.end(), pools.begin(), |
| [](const auto& pool) { return convertToV1_3(pool); }); |
| return {.inputs = request.inputs, .outputs = request.outputs, .pools = std::move(pools)}; |
| } |
| |
| V1_3::Request convertToV1_3(const V1_3::Request& request) { |
| return request; |
| } |
| |
| ErrorStatus uncheckedConvert(V1_0::ErrorStatus status) { |
| return handleError(convert(status)); |
| } |
| |
| ErrorStatus uncheckedConvert(V1_3::ErrorStatus status) { |
| return handleError(convert(status)); |
| } |
| |
| OperandType uncheckedConvert(V1_3::OperandType operandType) { |
| return handleError(unvalidatedConvert(operandType)); |
| } |
| |
| OperationType uncheckedConvert(V1_3::OperationType operandType) { |
| return handleError(unvalidatedConvert(operandType)); |
| } |
| |
| Operand::LifeTime uncheckedConvert(V1_3::OperandLifeTime lifetime) { |
| return handleError(unvalidatedConvert(lifetime)); |
| } |
| |
| MeasureTiming uncheckedConvert(V1_2::MeasureTiming measure) { |
| return handleError(convert(measure)); |
| } |
| |
| DataLocation uncheckedConvert(const V1_0::DataLocation& location) { |
| return handleError(unvalidatedConvert(location)); |
| } |
| |
| Operand uncheckedConvert(const V1_3::Operand& operand) { |
| return handleError(unvalidatedConvert(operand)); |
| } |
| |
| Operand::ExtraParams uncheckedConvert(const V1_2::Operand::ExtraParams& params) { |
| return handleError(unvalidatedConvert(params)); |
| } |
| |
| Operand::SymmPerChannelQuantParams uncheckedConvert(const V1_2::SymmPerChannelQuantParams& params) { |
| return handleError(unvalidatedConvert(params)); |
| } |
| |
| Operand::ExtensionParams uncheckedConvert(const hardware::hidl_vec<uint8_t>& params) { |
| return params; |
| } |
| |
| Operation uncheckedConvert(const V1_3::Operation& operation) { |
| return handleError(unvalidatedConvert(operation)); |
| } |
| |
| template <typename CanonicalType, typename HalType> |
| static std::vector<CanonicalType> convertVec(const hardware::hidl_vec<HalType>& items) { |
| std::vector<CanonicalType> result; |
| result.reserve(items.size()); |
| std::transform(items.begin(), items.end(), std::back_inserter(result), |
| [](const HalType& item) { return uncheckedConvert(item); }); |
| return result; |
| } |
| |
| Model uncheckedConvert(const V1_3::Model& model) { |
| return handleError(convert(model)); |
| } |
| |
| Model::Subgraph uncheckedConvert(const V1_3::Subgraph& subgraph) { |
| return handleError(unvalidatedConvert(subgraph)); |
| } |
| |
| Model::ExtensionNameAndPrefix uncheckedConvert(const V1_2::Model::ExtensionNameAndPrefix& x) { |
| return handleError(unvalidatedConvert(x)); |
| } |
| |
| Request uncheckedConvert(const V1_3::Request& request) { |
| return handleError(convert(request)); |
| } |
| |
| Request::Argument uncheckedConvert(const V1_0::RequestArgument& requestArgument) { |
| return handleError(unvalidatedConvert(requestArgument)); |
| } |
| |
| Request::MemoryPool uncheckedConvert(const V1_3::Request::MemoryPool& memoryPool) { |
| return handleError(unvalidatedConvert(memoryPool)); |
| } |
| |
| OutputShape uncheckedConvert(const V1_2::OutputShape& outputShape) { |
| return handleError(unvalidatedConvert(outputShape)); |
| } |
| |
| std::vector<OutputShape> uncheckedConvert( |
| const hardware::hidl_vec<V1_2::OutputShape>& outputShapes) { |
| return convertVec<OutputShape>(outputShapes); |
| } |
| |
| Capabilities uncheckedConvert(const V1_3::Capabilities& capabilities) { |
| return handleError(convert(capabilities)); |
| } |
| |
| Capabilities::OperandPerformance uncheckedConvert( |
| const V1_3::Capabilities::OperandPerformance& operandPerformance) { |
| return handleError(unvalidatedConvert(operandPerformance)); |
| } |
| |
| Capabilities::PerformanceInfo uncheckedConvert(const V1_0::PerformanceInfo& performanceInfo) { |
| return handleError(unvalidatedConvert(performanceInfo)); |
| } |
| |
| Extension uncheckedConvert(const V1_2::Extension& extension) { |
| return handleError(unvalidatedConvert(extension)); |
| } |
| |
| std::vector<Extension> uncheckedConvert(const hardware::hidl_vec<V1_2::Extension>& extensions) { |
| return convertVec<Extension>(extensions); |
| } |
| |
| Extension::OperandTypeInformation uncheckedConvert( |
| const V1_2::Extension::OperandTypeInformation& info) { |
| return handleError(unvalidatedConvert(info)); |
| } |
| |
| OptionalDuration uncheckedConvert(const V1_3::OptionalTimeoutDuration& timeoutDuration) { |
| return handleError(convert(timeoutDuration)); |
| } |
| |
| Timing uncheckedConvert(const V1_2::Timing& timing) { |
| return handleError(convert(timing)); |
| } |
| |
| V1_0::ErrorStatus convertToV1_0(ErrorStatus status) { |
| return static_cast<V1_0::ErrorStatus>(static_cast<int>(status)); |
| } |
| |
| V1_3::ErrorStatus convertToV1_3(ErrorStatus status) { |
| return handleError(V1_3::utils::convert(status)); |
| } |
| |
| V1_3::OperandType convertToV1_3(OperandType operandType) { |
| return handleError(V1_3::utils::unvalidatedConvert(operandType)); |
| } |
| |
| V1_3::OperationType convertToV1_3(OperationType operandType) { |
| return handleError(V1_3::utils::unvalidatedConvert(operandType)); |
| } |
| |
| V1_3::OperandLifeTime convertToV1_3(Operand::LifeTime lifetime) { |
| return handleError(V1_3::utils::unvalidatedConvert(lifetime)); |
| } |
| |
| V1_1::ExecutionPreference convertToV1_1(ExecutionPreference preference) { |
| return handleError(V1_1::utils::convert(preference)); |
| } |
| |
| V1_3::Priority convertToV1_3(Priority priority) { |
| return handleError(V1_3::utils::convert(priority)); |
| } |
| |
| V1_2::MeasureTiming convertToV1_2(MeasureTiming measure) { |
| return handleError(V1_2::utils::convert(measure)); |
| } |
| |
| V1_0::DataLocation convertToV1_0(const DataLocation& location) { |
| return handleError(V1_0::utils::unvalidatedConvert(location)); |
| } |
| |
| V1_3::Operand convertToV1_3(const Operand& operand) { |
| return handleError(V1_3::utils::unvalidatedConvert(operand)); |
| } |
| |
| V1_2::Operand::ExtraParams convertToV1_2(const Operand::ExtraParams& params) { |
| return handleError(V1_2::utils::unvalidatedConvert(params)); |
| } |
| |
| V1_2::SymmPerChannelQuantParams convertToV1_2(const Operand::SymmPerChannelQuantParams& params) { |
| return handleError(V1_2::utils::unvalidatedConvert(params)); |
| } |
| |
| hardware::hidl_vec<uint8_t> uncheckedConvert(const Operand::ExtensionParams& params) { |
| return params; |
| } |
| |
| V1_3::Operation convertToV1_3(const Operation& operation) { |
| return handleError(V1_3::utils::unvalidatedConvert(operation)); |
| } |
| |
| template <typename HalType, typename CanonicalType> |
| static hardware::hidl_vec<HalType> convertVecToV1_0(const std::vector<CanonicalType>& items) { |
| hardware::hidl_vec<HalType> result(items.size()); |
| std::transform(items.begin(), items.end(), result.begin(), |
| [](const CanonicalType& item) { return convertToV1_0(item); }); |
| return result; |
| } |
| |
| template <typename HalType, typename CanonicalType> |
| static hardware::hidl_vec<HalType> convertVecToV1_2(const std::vector<CanonicalType>& items) { |
| hardware::hidl_vec<HalType> result(items.size()); |
| std::transform(items.begin(), items.end(), result.begin(), |
| [](const CanonicalType& item) { return convertToV1_2(item); }); |
| return result; |
| } |
| |
| template <typename HalType, typename CanonicalType> |
| static hardware::hidl_vec<HalType> convertVecToV1_3(const std::vector<CanonicalType>& items) { |
| hardware::hidl_vec<HalType> result(items.size()); |
| std::transform(items.begin(), items.end(), result.begin(), |
| [](const CanonicalType& item) { return convertToV1_3(item); }); |
| return result; |
| } |
| |
| V1_2::OutputShape convertToV1_2(const OutputShape& outputShape) { |
| return handleError(V1_2::utils::unvalidatedConvert(outputShape)); |
| } |
| |
| hardware::hidl_vec<V1_2::OutputShape> convertToV1_2(const std::vector<OutputShape>& outputShapes) { |
| return convertVecToV1_2<V1_2::OutputShape>(outputShapes); |
| } |
| |
| V1_3::Model convertToV1_3(const Model& model) { |
| return handleError(V1_3::utils::convert(model)); |
| } |
| |
| V1_3::Subgraph convertToV1_3(const Model::Subgraph& subgraph) { |
| return handleError(V1_3::utils::unvalidatedConvert(subgraph)); |
| } |
| |
| V1_2::Model::ExtensionNameAndPrefix convertToV1_2(const Model::ExtensionNameAndPrefix& x) { |
| return handleError(V1_2::utils::unvalidatedConvert(x)); |
| } |
| |
| V1_3::Request convertToV1_3(const Request& request) { |
| return handleError(V1_3::utils::convert(request)); |
| } |
| |
| V1_0::RequestArgument convertToV1_0(const Request::Argument& requestArgument) { |
| return handleError(V1_0::utils::unvalidatedConvert(requestArgument)); |
| } |
| |
| V1_3::Request::MemoryPool convertToV1_3(const Request::MemoryPool& memoryPool) { |
| return handleError(V1_3::utils::unvalidatedConvert(memoryPool)); |
| } |
| |
| std::vector<Request::MemoryPool> uncheckedConvert( |
| const hardware::hidl_vec<V1_3::Request::MemoryPool>& memoryPools) { |
| return convertVec<Request::MemoryPool>(memoryPools); |
| } |
| |
| V1_3::OptionalTimePoint convertToV1_3(const OptionalTimePoint& timePoint) { |
| return handleError(V1_3::utils::convert(timePoint)); |
| } |
| |
| V1_3::OptionalTimeoutDuration convertToV1_3(const OptionalDuration& timeoutDuration) { |
| return handleError(V1_3::utils::convert(timeoutDuration)); |
| } |
| |
| V1_2::Timing convertToV1_2(const Timing& timing) { |
| return handleError(V1_2::utils::convert(timing)); |
| } |
| |
| V1_3::BufferRole convertToV1_3(const BufferRole& bufferRole) { |
| return handleError(V1_3::utils::unvalidatedConvert(bufferRole)); |
| } |
| |
| hardware::hidl_vec<V1_3::BufferRole> convertToV1_3(const std::vector<BufferRole>& bufferRoles) { |
| return convertVecToV1_3<V1_3::BufferRole>(bufferRoles); |
| } |
| |
| hardware::hidl_vec<uint8_t> convertToV1_0(const Model::OperandValues& operandValues) { |
| return handleError(V1_0::utils::unvalidatedConvert(operandValues)); |
| } |
| |
| hardware::hidl_memory convertToV1_0(const SharedMemory& memory) { |
| return handleError(V1_0::utils::unvalidatedConvert(memory)); |
| } |
| |
| SharedMemory uncheckedConvert(const hardware::hidl_memory& memory) { |
| return handleError(convert(memory)); |
| } |
| |
| hardware::hidl_vec<hardware::hidl_memory> convertToV1_0(const std::vector<SharedMemory>& memories) { |
| return convertVecToV1_0<hardware::hidl_memory>(memories); |
| } |
| |
| std::vector<SharedMemory> uncheckedConvert( |
| const hardware::hidl_vec<hardware::hidl_memory>& memories) { |
| return convertVec<SharedMemory>(memories); |
| } |
| |
| std::vector<Model::Subgraph> uncheckedConvert(const hardware::hidl_vec<V1_3::Subgraph>& subgraphs) { |
| return convertVec<Model::Subgraph>(subgraphs); |
| } |
| |
| std::vector<Operand> uncheckedConvert(const hardware::hidl_vec<V1_3::Operand>& operands) { |
| return convertVec<Operand>(operands); |
| } |
| |
| } // namespace nn |
| } // namespace android |