/* * 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. */ // This file contains pre-canonical-types utility code and includes HAL // utilities. LegacyUtils.h is the subset of these utilities that do not touch // HAL. #ifndef ANDROID_FRAMEWORKS_ML_NN_COMMON_LEGACY_HAL_UTILS_H #define ANDROID_FRAMEWORKS_ML_NN_COMMON_LEGACY_HAL_UTILS_H #include #include #include #include #include #include #include #include #include "HalInterfaces.h" #include "LegacyUtils.h" #include "NeuralNetworks.h" #include "ValidateHal.h" namespace android { namespace nn { using LegacyClock = std::chrono::steady_clock; using LegacyDuration = std::chrono::duration; using LegacyOptionalDuration = std::optional; using LegacyTimePoint = std::chrono::time_point; using LegacyOptionalTimePoint = std::optional; // Make an optional deadline from an V1_3::OptionalTimePoint. LegacyOptionalTimePoint makeDeadline(const V1_3::OptionalTimePoint& timePoint); // Make an optional deadline from an V1_3::OptionalDuration. LegacyOptionalTimePoint makeDeadline(const V1_3::OptionalTimeoutDuration& optionalDuration); // Returns true if the deadline has passed. Returns false if either the deadline // has not been exceeded or if the deadline is not present. bool hasDeadlinePassed(const LegacyOptionalTimePoint& deadline); // Ensure that every user of FalseyErrorStream is linked to the // correct instance, using the correct LOG_TAG namespace { template struct VersionedType {}; template <> struct VersionedType { using OperandPerformance = V1_2::Capabilities::OperandPerformance; using OperandType = V1_2::OperandType; }; template <> struct VersionedType { using OperandPerformance = V1_3::Capabilities::OperandPerformance; using OperandType = V1_3::OperandType; }; template using VersionedOperandPerformance = typename VersionedType::OperandPerformance; template using VersionedOperandType = typename VersionedType::OperandType; } // namespace // Return a vector with one entry for each non-extension OperandType except // SUBGRAPH, set to the specified PerformanceInfo value. The vector will be // sorted by OperandType. // // Control flow (OperandType::SUBGRAPH) operation performance is specified // separately using Capabilities::ifPerformance and // Capabilities::whilePerformance. template hardware::hidl_vec> nonExtensionOperandPerformance( V1_0::PerformanceInfo perf); // Update the vector entry corresponding to the specified OperandType with the // specified PerformanceInfo value. The vector must already have an entry for // that OperandType, and must be sorted by OperandType. void update(hardware::hidl_vec* operandPerformance, V1_2::OperandType type, V1_0::PerformanceInfo perf); void update(hardware::hidl_vec* operandPerformance, V1_3::OperandType type, V1_0::PerformanceInfo perf); // Look for a vector entry corresponding to the specified OperandType. If // found, return the associated PerformanceInfo. If not, return a pessimistic // PerformanceInfo (FLT_MAX). The vector must be sorted by OperandType. V1_0::PerformanceInfo lookup( const hardware::hidl_vec& operandPerformance, V1_2::OperandType type); V1_0::PerformanceInfo lookup( const hardware::hidl_vec& operandPerformance, V1_3::OperandType type); // Returns true if an operand type is an extension type. bool isExtensionOperandType(V1_3::OperandType type); // Returns true if an operation type is an extension type. bool isExtensionOperationType(V1_3::OperationType type); // Returns the amount of space needed to store a value of the specified // dimensions and type. For a tensor with unspecified rank or at least one // unspecified dimension, returns zero. // // Aborts if the specified type is an extension type. // Aborts if the size would overflow the return type. // // See also TypeManager::getSizeOfData(OperandType, const std::vector&). uint32_t nonExtensionOperandSizeOfData(V1_3::OperandType type, const std::vector& dimensions); // Returns the amount of space needed to store a value of the dimensions and // type of this operand. For a tensor with unspecified rank or at least one // unspecified dimension, returns zero. // // Aborts if the specified type is an extension type. // Aborts if the size would overflow the return type. // // See also TypeManager::getSizeOfData(const Operand&). inline uint32_t nonExtensionOperandSizeOfData(const V1_3::Operand& operand) { return nonExtensionOperandSizeOfData(operand.type, operand.dimensions); } // Returns true if the amount of space needed to store a value of the specified // dimensions and element size overflows the uint32_t type. // // Aborts if the specified type is an extension type. // // See also TypeManager::sizeOfDataOverflowsUInt32(OperandType, const std::vector&). bool nonExtensionOperandSizeOfDataOverflowsUInt32(V1_3::OperandType type, const std::vector& dimensions); // Returns the name of the operation type in ASCII. std::string getOperationName(V1_3::OperationType opCode); // Returns the name of the operand type in ASCII. std::string getOperandTypeName(V1_3::OperandType type); // Whether an operand of tensor type has unspecified dimensions. // // Undefined behavior if the operand type is a scalar type. bool tensorHasUnspecifiedDimensions(V1_3::OperandType type, const std::vector& dimensions); bool tensorHasUnspecifiedDimensions(const V1_3::Operand& operand); // Does a detailed LOG(INFO) of the model void logModelToInfo(const V1_0::Model& model); void logModelToInfo(const V1_1::Model& model); void logModelToInfo(const V1_2::Model& model); void logModelToInfo(const V1_3::Model& model); bool validateOperandSymmPerChannelQuantParams( const V1_3::Operand& halOperand, const ANeuralNetworksSymmPerChannelQuantParams& channelQuant, const char* tag); // Convert ANEURALNETWORKS_* result code to ErrorStatus. // Not guaranteed to be a 1-to-1 mapping. V1_3::ErrorStatus convertResultCodeToHalErrorStatus(int resultCode); // Convert ErrorStatus to ANEURALNETWORKS_* result code. // Not guaranteed to be a 1-to-1 mapping. int convertErrorStatusToResultCode(V1_3::ErrorStatus status); // Convert execution results to runtime format. Additionally checks that the // returned results abide by the HAL specification, and logs an error if the // result violates the specification. std::tuple, Timing> getExecutionResult( V1_3::ErrorStatus status, const hardware::hidl_vec& outputShapes, const V1_2::Timing& timing); // Forward declaration for type defined in CpuExecutor.h. class RunTimePoolInfo; bool setRunTimePoolInfosFromHidlMemories(std::vector* poolInfos, const hardware::hidl_vec& pools); // Versioning bool compliantWithV1_0(const V1_0::Capabilities& capabilities); bool compliantWithV1_0(const V1_1::Capabilities& capabilities); bool compliantWithV1_0(const V1_2::Capabilities& capabilities); bool compliantWithV1_0(const V1_3::Capabilities& capabilities); bool compliantWithV1_1(const V1_0::Capabilities& capabilities); bool compliantWithV1_1(const V1_1::Capabilities& capabilities); bool compliantWithV1_1(const V1_2::Capabilities& capabilities); bool compliantWithV1_1(const V1_3::Capabilities& capabilities); bool compliantWithV1_2(const V1_0::Capabilities& capabilities); bool compliantWithV1_2(const V1_1::Capabilities& capabilities); bool compliantWithV1_2(const V1_2::Capabilities& capabilities); bool compliantWithV1_2(const V1_3::Capabilities& capabilities); bool compliantWithV1_3(const V1_0::Capabilities& capabilities); bool compliantWithV1_3(const V1_1::Capabilities& capabilities); bool compliantWithV1_3(const V1_2::Capabilities& capabilities); bool compliantWithV1_3(const V1_3::Capabilities& capabilities); // If noncompliantOperations != nullptr, then // precondition: noncompliantOperations->empty() // postcondition: *noncompliantOperations consists of the indices of the noncompliant // operations; if the compliance check fails for some reason // other than a noncompliant operation, // *noncompliantOperations consists of the indices of all operations bool compliantWithV1_0(const V1_0::Model& model); bool compliantWithV1_0(const V1_1::Model& model); bool compliantWithV1_0(const V1_2::Model& model, std::set* noncompliantOperations = nullptr); bool compliantWithV1_0(const V1_3::Model& model, std::set* noncompliantOperations = nullptr); bool compliantWithV1_1(const V1_0::Model& model); bool compliantWithV1_1(const V1_1::Model& model); bool compliantWithV1_1(const V1_2::Model& model, std::set* noncompliantOperations = nullptr); bool compliantWithV1_1(const V1_3::Model& model, std::set* noncompliantOperations = nullptr); bool compliantWithV1_2(const V1_0::Model& model); bool compliantWithV1_2(const V1_1::Model& model); bool compliantWithV1_2(const V1_2::Model& model, std::set* noncompliantOperations = nullptr); bool compliantWithV1_2(const V1_3::Model& model, std::set* noncompliantOperations = nullptr); V1_0::ErrorStatus convertToV1_0(V1_0::ErrorStatus status); V1_0::ErrorStatus convertToV1_0(V1_3::ErrorStatus status); V1_3::ErrorStatus convertToV1_3(V1_0::ErrorStatus status); V1_3::ErrorStatus convertToV1_3(V1_3::ErrorStatus status); V1_0::Capabilities convertToV1_0(const V1_0::Capabilities& capabilities); V1_0::Capabilities convertToV1_0(const V1_1::Capabilities& capabilities); V1_0::Capabilities convertToV1_0(const V1_2::Capabilities& capabilities); V1_0::Capabilities convertToV1_0(const V1_3::Capabilities& capabilities); V1_1::Capabilities convertToV1_1(const V1_0::Capabilities& capabilities); V1_1::Capabilities convertToV1_1(const V1_1::Capabilities& capabilities); V1_1::Capabilities convertToV1_1(const V1_2::Capabilities& capabilities); V1_1::Capabilities convertToV1_1(const V1_3::Capabilities& capabilities); V1_2::Capabilities convertToV1_2(const V1_0::Capabilities& capabilities); V1_2::Capabilities convertToV1_2(const V1_1::Capabilities& capabilities); V1_2::Capabilities convertToV1_2(const V1_2::Capabilities& capabilities); V1_2::Capabilities convertToV1_2(const V1_3::Capabilities& capabilities); V1_3::Capabilities convertToV1_3(const V1_0::Capabilities& capabilities); V1_3::Capabilities convertToV1_3(const V1_1::Capabilities& capabilities); V1_3::Capabilities convertToV1_3(const V1_2::Capabilities& capabilities); V1_3::Capabilities convertToV1_3(const V1_3::Capabilities& capabilities); V1_0::Model convertToV1_0(const V1_0::Model& model); V1_0::Model convertToV1_0(const V1_1::Model& model); V1_0::Model convertToV1_0(const V1_2::Model& model); V1_0::Model convertToV1_0(const V1_3::Model& model); V1_1::Model convertToV1_1(const V1_0::Model& model); V1_1::Model convertToV1_1(const V1_1::Model& model); V1_1::Model convertToV1_1(const V1_2::Model& model); V1_1::Model convertToV1_1(const V1_3::Model& model); V1_2::Model convertToV1_2(const V1_0::Model& model); V1_2::Model convertToV1_2(const V1_1::Model& model); V1_2::Model convertToV1_2(const V1_2::Model& model); V1_2::Model convertToV1_2(const V1_3::Model& model); V1_3::Model convertToV1_3(const V1_0::Model& model); V1_3::Model convertToV1_3(const V1_1::Model& model); V1_3::Model convertToV1_3(const V1_2::Model& model); V1_3::Model convertToV1_3(const V1_3::Model& model); V1_0::OperationType uncheckedConvertToV1_0(V1_3::OperationType type); V1_1::OperationType uncheckedConvertToV1_1(V1_3::OperationType type); V1_2::OperationType uncheckedConvertToV1_2(V1_3::OperationType type); V1_0::Operand convertToV1_0(const V1_2::Operand& operand); V1_0::Operand convertToV1_0(const V1_3::Operand& operand); V1_2::Operand convertToV1_2(const V1_0::Operand& operand); V1_2::Operand convertToV1_2(const V1_3::Operand& operand); V1_3::Operand convertToV1_3(const V1_0::Operand& operand); V1_3::Operand convertToV1_3(const V1_2::Operand& operand); V1_3::Operand convertToV1_3(const V1_3::Operand& operand); hardware::hidl_vec convertToV1_0(const hardware::hidl_vec& operands); hardware::hidl_vec convertToV1_0(const hardware::hidl_vec& operands); hardware::hidl_vec convertToV1_0(const hardware::hidl_vec& operands); hardware::hidl_vec convertToV1_2(const hardware::hidl_vec& operands); hardware::hidl_vec convertToV1_2(const hardware::hidl_vec& operands); hardware::hidl_vec convertToV1_2(const hardware::hidl_vec& operands); hardware::hidl_vec convertToV1_3(const hardware::hidl_vec& operands); hardware::hidl_vec convertToV1_3(const hardware::hidl_vec& operands); hardware::hidl_vec convertToV1_3(const hardware::hidl_vec& operands); bool compliantWithV1_0(const V1_0::Request& request); bool compliantWithV1_0(const V1_3::Request& request); bool compliantWithV1_2(const V1_3::Request& request); V1_0::Request convertToV1_0(const V1_0::Request& request); V1_0::Request convertToV1_0(const V1_3::Request& request); V1_0::Request convertToV1_2(const V1_3::Request& request); V1_3::Request convertToV1_3(const V1_0::Request& request); V1_3::Request convertToV1_3(const V1_3::Request& request); bool compliantWithV1_0(V1_0::OperandLifeTime lifetime); bool compliantWithV1_0(V1_3::OperandLifeTime lifetime); bool compliantWithV1_3(V1_0::OperandLifeTime lifetime); bool compliantWithV1_3(V1_3::OperandLifeTime lifetime); V1_0::OperandLifeTime convertToV1_0(V1_0::OperandLifeTime lifetime); V1_0::OperandLifeTime convertToV1_0(V1_3::OperandLifeTime lifetime); V1_3::OperandLifeTime convertToV1_3(V1_0::OperandLifeTime lifetime); V1_3::OperandLifeTime convertToV1_3(V1_3::OperandLifeTime lifetime); constexpr V1_3::Priority convertToHalPriority(int32_t priority) { switch (priority) { case ANEURALNETWORKS_PRIORITY_LOW: return V1_3::Priority::LOW; case ANEURALNETWORKS_PRIORITY_MEDIUM: return V1_3::Priority::MEDIUM; case ANEURALNETWORKS_PRIORITY_HIGH: return V1_3::Priority::HIGH; } LOG(FATAL) << "unrecognized priority: " << priority; return {}; } // DEPRECATED. Use checked conversions from nnapi/hal/1.X/Conversions.h. Capabilities::OperandPerformance uncheckedConvert( const V1_3::Capabilities::OperandPerformance& operandPerformance); Capabilities::PerformanceInfo uncheckedConvert(const V1_0::PerformanceInfo& performanceInfo); Capabilities uncheckedConvert(const V1_3::Capabilities& capabilities); DataLocation uncheckedConvert(const V1_0::DataLocation& location); ErrorStatus uncheckedConvert(V1_0::ErrorStatus status); ErrorStatus uncheckedConvert(V1_3::ErrorStatus status); Extension::OperandTypeInformation uncheckedConvert(const V1_2::Extension::OperandTypeInformation&); Extension uncheckedConvert(const V1_2::Extension& extension); hardware::hidl_vec uncheckedConvert(const Operand::ExtensionParams& params); MeasureTiming uncheckedConvert(V1_2::MeasureTiming measure); SharedMemory uncheckedConvert(const hardware::hidl_memory& memory); Model::ExtensionNameAndPrefix uncheckedConvert(const V1_2::Model::ExtensionNameAndPrefix&); Model::Subgraph uncheckedConvert(const V1_3::Subgraph& subgraph); Model uncheckedConvert(const V1_3::Model& model); Operand::ExtensionParams uncheckedConvert(const hardware::hidl_vec& params); Operand::ExtraParams uncheckedConvert(const V1_2::Operand::ExtraParams& params); Operand::LifeTime uncheckedConvert(V1_3::OperandLifeTime lifetime); Operand::SymmPerChannelQuantParams uncheckedConvert(const V1_2::SymmPerChannelQuantParams& params); OperandType uncheckedConvert(V1_3::OperandType operandType); Operand uncheckedConvert(const V1_3::Operand& operand); OperationType uncheckedConvert(V1_3::OperationType operationType); Operation uncheckedConvert(const V1_3::Operation& operation); OptionalDuration uncheckedConvert(const V1_3::OptionalTimeoutDuration& timeoutDuration); OutputShape uncheckedConvert(const V1_2::OutputShape& outputShape); Request::Argument uncheckedConvert(const V1_0::RequestArgument& requestArgument); Request::MemoryPool uncheckedConvert(const V1_3::Request::MemoryPool& memoryPool); Request uncheckedConvert(const V1_3::Request& request); std::vector uncheckedConvert(const hardware::hidl_vec& extensions); std::vector uncheckedConvert( const hardware::hidl_vec& memories); std::vector uncheckedConvert(const hardware::hidl_vec& subgraphs); std::vector uncheckedConvert(const hardware::hidl_vec& operands); std::vector uncheckedConvert( const hardware::hidl_vec& outputShapes); std::vector uncheckedConvert( const hardware::hidl_vec& memoryPools); Timing uncheckedConvert(const V1_2::Timing& timing); // DEPRECATED. Use conversions from nnapi/hal/1.X/Conversions.h. hardware::hidl_memory convertToV1_0(const SharedMemory& memory); hardware::hidl_vec convertToV1_0(const std::vector& memories); hardware::hidl_vec convertToV1_0(const Model::OperandValues& operandValues); hardware::hidl_vec convertToV1_2(const std::vector& outputShapes); hardware::hidl_vec convertToV1_3(const std::vector& bufferRoles); V1_0::DataLocation convertToV1_0(const DataLocation& location); V1_0::ErrorStatus convertToV1_0(ErrorStatus status); V1_0::RequestArgument convertToV1_0(const Request::Argument& requestArgument); V1_1::ExecutionPreference convertToV1_1(ExecutionPreference preference); V1_2::MeasureTiming convertToV1_2(MeasureTiming measure); V1_2::Model::ExtensionNameAndPrefix convertToV1_2(const Model::ExtensionNameAndPrefix&); V1_2::Operand::ExtraParams convertToV1_2(const Operand::ExtraParams& params); V1_2::OutputShape convertToV1_2(const OutputShape& outputShape); V1_2::SymmPerChannelQuantParams convertToV1_2(const Operand::SymmPerChannelQuantParams& params); V1_2::Timing convertToV1_2(const Timing& timing); V1_3::BufferRole convertToV1_3(const BufferRole& bufferRole); V1_3::ErrorStatus convertToV1_3(ErrorStatus status); V1_3::Model convertToV1_3(const Model& model); V1_3::Operand convertToV1_3(const Operand& operand); V1_3::OperandLifeTime convertToV1_3(Operand::LifeTime lifetime); V1_3::OperandType convertToV1_3(OperandType operandType); V1_3::Operation convertToV1_3(const Operation& operation); V1_3::OperationType convertToV1_3(OperationType operationType); V1_3::OptionalTimeoutDuration convertToV1_3(const OptionalDuration& timeoutDuration); V1_3::OptionalTimePoint convertToV1_3(const OptionalTimePoint& timePoint); V1_3::Priority convertToV1_3(Priority priority); V1_3::Request convertToV1_3(const Request& request); V1_3::Request::MemoryPool convertToV1_3(const Request::MemoryPool& memoryPool); V1_3::Subgraph convertToV1_3(const Model::Subgraph& model); } // namespace nn } // namespace android #endif // ANDROID_FRAMEWORKS_ML_NN_COMMON_LEGACY_HAL_UTILS_H