1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 // This file contains pre-canonical-types utility code and includes HAL 17 // utilities. LegacyUtils.h is the subset of these utilities that do not touch 18 // HAL. 19 20 #ifndef ANDROID_PACKAGES_MODULES_NEURALNETWORKS_COMMON_LEGACY_HAL_UTILS_H 21 #define ANDROID_PACKAGES_MODULES_NEURALNETWORKS_COMMON_LEGACY_HAL_UTILS_H 22 23 #include <android-base/logging.h> 24 #include <nnapi/TypeUtils.h> 25 #include <nnapi/Types.h> 26 27 #include <set> 28 #include <string> 29 #include <tuple> 30 #include <utility> 31 #include <vector> 32 33 #include "HalInterfaces.h" 34 #include "LegacyUtils.h" 35 #include "NeuralNetworks.h" 36 #include "ValidateHal.h" 37 38 namespace android { 39 namespace nn { 40 41 using LegacyClock = std::chrono::steady_clock; 42 using LegacyDuration = std::chrono::duration<uint64_t, std::nano>; 43 using LegacyOptionalDuration = std::optional<LegacyDuration>; 44 using LegacyTimePoint = std::chrono::time_point<std::chrono::steady_clock, LegacyDuration>; 45 using LegacyOptionalTimePoint = std::optional<LegacyTimePoint>; 46 47 // Make an optional deadline from an V1_3::OptionalTimePoint. 48 LegacyOptionalTimePoint makeDeadline(const V1_3::OptionalTimePoint& timePoint); 49 50 // Make an optional deadline from an V1_3::OptionalDuration. 51 LegacyOptionalTimePoint makeDeadline(const V1_3::OptionalTimeoutDuration& optionalDuration); 52 53 // Returns true if the deadline has passed. Returns false if either the deadline 54 // has not been exceeded or if the deadline is not present. 55 bool hasDeadlinePassed(const LegacyOptionalTimePoint& deadline); 56 57 // Ensure that every user of FalseyErrorStream is linked to the 58 // correct instance, using the correct LOG_TAG 59 namespace { 60 61 template <HalVersion version> 62 struct VersionedType {}; 63 64 template <> 65 struct VersionedType<HalVersion::V1_2> { 66 using OperandPerformance = V1_2::Capabilities::OperandPerformance; 67 using OperandType = V1_2::OperandType; 68 }; 69 70 template <> 71 struct VersionedType<HalVersion::V1_3> { 72 using OperandPerformance = V1_3::Capabilities::OperandPerformance; 73 using OperandType = V1_3::OperandType; 74 }; 75 76 template <HalVersion version> 77 using VersionedOperandPerformance = typename VersionedType<version>::OperandPerformance; 78 template <HalVersion version> 79 using VersionedOperandType = typename VersionedType<version>::OperandType; 80 81 } // namespace 82 83 // Return a vector with one entry for each non-extension OperandType except 84 // SUBGRAPH, set to the specified PerformanceInfo value. The vector will be 85 // sorted by OperandType. 86 // 87 // Control flow (OperandType::SUBGRAPH) operation performance is specified 88 // separately using Capabilities::ifPerformance and 89 // Capabilities::whilePerformance. 90 template <HalVersion version> 91 hardware::hidl_vec<VersionedOperandPerformance<version>> nonExtensionOperandPerformance( 92 V1_0::PerformanceInfo perf); 93 94 // Update the vector entry corresponding to the specified OperandType with the 95 // specified PerformanceInfo value. The vector must already have an entry for 96 // that OperandType, and must be sorted by OperandType. 97 void update(hardware::hidl_vec<V1_2::Capabilities::OperandPerformance>* operandPerformance, 98 V1_2::OperandType type, V1_0::PerformanceInfo perf); 99 void update(hardware::hidl_vec<V1_3::Capabilities::OperandPerformance>* operandPerformance, 100 V1_3::OperandType type, V1_0::PerformanceInfo perf); 101 102 // Look for a vector entry corresponding to the specified OperandType. If 103 // found, return the associated PerformanceInfo. If not, return a pessimistic 104 // PerformanceInfo (FLT_MAX). The vector must be sorted by OperandType. 105 V1_0::PerformanceInfo lookup( 106 const hardware::hidl_vec<V1_2::Capabilities::OperandPerformance>& operandPerformance, 107 V1_2::OperandType type); 108 V1_0::PerformanceInfo lookup( 109 const hardware::hidl_vec<V1_3::Capabilities::OperandPerformance>& operandPerformance, 110 V1_3::OperandType type); 111 112 // Returns true if an operand type is an extension type. 113 bool isExtensionOperandType(V1_3::OperandType type); 114 115 // Returns true if an operation type is an extension type. 116 bool isExtensionOperationType(V1_3::OperationType type); 117 118 // Returns the amount of space needed to store a value of the specified 119 // dimensions and type. For a tensor with unspecified rank or at least one 120 // unspecified dimension, returns zero. 121 // 122 // Aborts if the specified type is an extension type. 123 // Aborts if the size would overflow the return type. 124 // 125 // See also TypeManager::getSizeOfData(OperandType, const std::vector<uint32_t>&). 126 uint32_t nonExtensionOperandSizeOfData(V1_3::OperandType type, 127 const std::vector<uint32_t>& dimensions); 128 129 // Returns the amount of space needed to store a value of the dimensions and 130 // type of this operand. For a tensor with unspecified rank or at least one 131 // unspecified dimension, returns zero. 132 // 133 // Aborts if the specified type is an extension type. 134 // Aborts if the size would overflow the return type. 135 // 136 // See also TypeManager::getSizeOfData(const Operand&). 137 inline uint32_t nonExtensionOperandSizeOfData(const V1_3::Operand& operand) { 138 return nonExtensionOperandSizeOfData(operand.type, operand.dimensions); 139 } 140 141 // Returns true if the amount of space needed to store a value of the specified 142 // dimensions and element size overflows the uint32_t type. 143 // 144 // Aborts if the specified type is an extension type. 145 // 146 // See also TypeManager::sizeOfDataOverflowsUInt32(OperandType, const std::vector<uint32_t>&). 147 bool nonExtensionOperandSizeOfDataOverflowsUInt32(V1_3::OperandType type, 148 const std::vector<uint32_t>& dimensions); 149 150 // Returns the name of the operation type in ASCII. 151 std::string getOperationName(V1_3::OperationType opCode); 152 153 // Returns the name of the operand type in ASCII. 154 std::string getOperandTypeName(V1_3::OperandType type); 155 156 // Whether an operand of tensor type has unspecified dimensions. 157 // 158 // Undefined behavior if the operand type is a scalar type. 159 bool tensorHasUnspecifiedDimensions(V1_3::OperandType type, 160 const std::vector<uint32_t>& dimensions); 161 bool tensorHasUnspecifiedDimensions(const V1_3::Operand& operand); 162 163 // Does a detailed LOG(INFO) of the model 164 void logModelToInfo(const V1_0::Model& model); 165 void logModelToInfo(const V1_1::Model& model); 166 void logModelToInfo(const V1_2::Model& model); 167 void logModelToInfo(const V1_3::Model& model); 168 169 bool validateOperandSymmPerChannelQuantParams( 170 const V1_3::Operand& halOperand, 171 const ANeuralNetworksSymmPerChannelQuantParams& channelQuant, const char* tag); 172 173 // Convert ANEURALNETWORKS_* result code to ErrorStatus. 174 // Not guaranteed to be a 1-to-1 mapping. 175 V1_3::ErrorStatus convertResultCodeToHalErrorStatus(int resultCode); 176 177 // Convert ErrorStatus to ANEURALNETWORKS_* result code. 178 // Not guaranteed to be a 1-to-1 mapping. 179 int convertErrorStatusToResultCode(V1_3::ErrorStatus status); 180 181 // Convert execution results to runtime format. Additionally checks that the 182 // returned results abide by the HAL specification, and logs an error if the 183 // result violates the specification. 184 std::tuple<int, std::vector<OutputShape>, Timing> getExecutionResult( 185 V1_3::ErrorStatus status, const hardware::hidl_vec<V1_2::OutputShape>& outputShapes, 186 const V1_2::Timing& timing); 187 188 // Forward declaration for type defined in CpuExecutor.h. 189 class RunTimePoolInfo; 190 191 bool setRunTimePoolInfosFromHidlMemories(std::vector<RunTimePoolInfo>* poolInfos, 192 const hardware::hidl_vec<hardware::hidl_memory>& pools); 193 194 // Versioning 195 196 bool compliantWithV1_0(const V1_0::Capabilities& capabilities); 197 bool compliantWithV1_0(const V1_1::Capabilities& capabilities); 198 bool compliantWithV1_0(const V1_2::Capabilities& capabilities); 199 bool compliantWithV1_0(const V1_3::Capabilities& capabilities); 200 bool compliantWithV1_1(const V1_0::Capabilities& capabilities); 201 bool compliantWithV1_1(const V1_1::Capabilities& capabilities); 202 bool compliantWithV1_1(const V1_2::Capabilities& capabilities); 203 bool compliantWithV1_1(const V1_3::Capabilities& capabilities); 204 bool compliantWithV1_2(const V1_0::Capabilities& capabilities); 205 bool compliantWithV1_2(const V1_1::Capabilities& capabilities); 206 bool compliantWithV1_2(const V1_2::Capabilities& capabilities); 207 bool compliantWithV1_2(const V1_3::Capabilities& capabilities); 208 bool compliantWithV1_3(const V1_0::Capabilities& capabilities); 209 bool compliantWithV1_3(const V1_1::Capabilities& capabilities); 210 bool compliantWithV1_3(const V1_2::Capabilities& capabilities); 211 bool compliantWithV1_3(const V1_3::Capabilities& capabilities); 212 213 // If noncompliantOperations != nullptr, then 214 // precondition: noncompliantOperations->empty() 215 // postcondition: *noncompliantOperations consists of the indices of the noncompliant 216 // operations; if the compliance check fails for some reason 217 // other than a noncompliant operation, 218 // *noncompliantOperations consists of the indices of all operations 219 bool compliantWithV1_0(const V1_0::Model& model); 220 bool compliantWithV1_0(const V1_1::Model& model); 221 bool compliantWithV1_0(const V1_2::Model& model, 222 std::set<uint32_t>* noncompliantOperations = nullptr); 223 bool compliantWithV1_0(const V1_3::Model& model, 224 std::set<uint32_t>* noncompliantOperations = nullptr); 225 bool compliantWithV1_1(const V1_0::Model& model); 226 bool compliantWithV1_1(const V1_1::Model& model); 227 bool compliantWithV1_1(const V1_2::Model& model, 228 std::set<uint32_t>* noncompliantOperations = nullptr); 229 bool compliantWithV1_1(const V1_3::Model& model, 230 std::set<uint32_t>* noncompliantOperations = nullptr); 231 bool compliantWithV1_2(const V1_0::Model& model); 232 bool compliantWithV1_2(const V1_1::Model& model); 233 bool compliantWithV1_2(const V1_2::Model& model, 234 std::set<uint32_t>* noncompliantOperations = nullptr); 235 bool compliantWithV1_2(const V1_3::Model& model, 236 std::set<uint32_t>* noncompliantOperations = nullptr); 237 238 V1_0::ErrorStatus convertToV1_0(V1_0::ErrorStatus status); 239 V1_0::ErrorStatus convertToV1_0(V1_3::ErrorStatus status); 240 V1_3::ErrorStatus convertToV1_3(V1_0::ErrorStatus status); 241 V1_3::ErrorStatus convertToV1_3(V1_3::ErrorStatus status); 242 243 V1_0::Capabilities convertToV1_0(const V1_0::Capabilities& capabilities); 244 V1_0::Capabilities convertToV1_0(const V1_1::Capabilities& capabilities); 245 V1_0::Capabilities convertToV1_0(const V1_2::Capabilities& capabilities); 246 V1_0::Capabilities convertToV1_0(const V1_3::Capabilities& capabilities); 247 V1_1::Capabilities convertToV1_1(const V1_0::Capabilities& capabilities); 248 V1_1::Capabilities convertToV1_1(const V1_1::Capabilities& capabilities); 249 V1_1::Capabilities convertToV1_1(const V1_2::Capabilities& capabilities); 250 V1_1::Capabilities convertToV1_1(const V1_3::Capabilities& capabilities); 251 V1_2::Capabilities convertToV1_2(const V1_0::Capabilities& capabilities); 252 V1_2::Capabilities convertToV1_2(const V1_1::Capabilities& capabilities); 253 V1_2::Capabilities convertToV1_2(const V1_2::Capabilities& capabilities); 254 V1_2::Capabilities convertToV1_2(const V1_3::Capabilities& capabilities); 255 V1_3::Capabilities convertToV1_3(const V1_0::Capabilities& capabilities); 256 V1_3::Capabilities convertToV1_3(const V1_1::Capabilities& capabilities); 257 V1_3::Capabilities convertToV1_3(const V1_2::Capabilities& capabilities); 258 V1_3::Capabilities convertToV1_3(const V1_3::Capabilities& capabilities); 259 260 V1_0::Model convertToV1_0(const V1_0::Model& model); 261 V1_0::Model convertToV1_0(const V1_1::Model& model); 262 V1_0::Model convertToV1_0(const V1_2::Model& model); 263 V1_0::Model convertToV1_0(const V1_3::Model& model); 264 V1_1::Model convertToV1_1(const V1_0::Model& model); 265 V1_1::Model convertToV1_1(const V1_1::Model& model); 266 V1_1::Model convertToV1_1(const V1_2::Model& model); 267 V1_1::Model convertToV1_1(const V1_3::Model& model); 268 V1_2::Model convertToV1_2(const V1_0::Model& model); 269 V1_2::Model convertToV1_2(const V1_1::Model& model); 270 V1_2::Model convertToV1_2(const V1_2::Model& model); 271 V1_2::Model convertToV1_2(const V1_3::Model& model); 272 V1_3::Model convertToV1_3(const V1_0::Model& model); 273 V1_3::Model convertToV1_3(const V1_1::Model& model); 274 V1_3::Model convertToV1_3(const V1_2::Model& model); 275 V1_3::Model convertToV1_3(const V1_3::Model& model); 276 277 V1_0::OperationType uncheckedConvertToV1_0(V1_3::OperationType type); 278 V1_1::OperationType uncheckedConvertToV1_1(V1_3::OperationType type); 279 V1_2::OperationType uncheckedConvertToV1_2(V1_3::OperationType type); 280 281 V1_0::Operand convertToV1_0(const V1_2::Operand& operand); 282 V1_0::Operand convertToV1_0(const V1_3::Operand& operand); 283 V1_2::Operand convertToV1_2(const V1_0::Operand& operand); 284 V1_2::Operand convertToV1_2(const V1_3::Operand& operand); 285 V1_3::Operand convertToV1_3(const V1_0::Operand& operand); 286 V1_3::Operand convertToV1_3(const V1_2::Operand& operand); 287 V1_3::Operand convertToV1_3(const V1_3::Operand& operand); 288 289 hardware::hidl_vec<V1_0::Operand> convertToV1_0(const hardware::hidl_vec<V1_0::Operand>& operands); 290 hardware::hidl_vec<V1_0::Operand> convertToV1_0(const hardware::hidl_vec<V1_2::Operand>& operands); 291 hardware::hidl_vec<V1_0::Operand> convertToV1_0(const hardware::hidl_vec<V1_3::Operand>& operands); 292 hardware::hidl_vec<V1_2::Operand> convertToV1_2(const hardware::hidl_vec<V1_0::Operand>& operands); 293 hardware::hidl_vec<V1_2::Operand> convertToV1_2(const hardware::hidl_vec<V1_2::Operand>& operands); 294 hardware::hidl_vec<V1_2::Operand> convertToV1_2(const hardware::hidl_vec<V1_3::Operand>& operands); 295 hardware::hidl_vec<V1_3::Operand> convertToV1_3(const hardware::hidl_vec<V1_0::Operand>& operands); 296 hardware::hidl_vec<V1_3::Operand> convertToV1_3(const hardware::hidl_vec<V1_2::Operand>& operands); 297 hardware::hidl_vec<V1_3::Operand> convertToV1_3(const hardware::hidl_vec<V1_3::Operand>& operands); 298 299 bool compliantWithV1_0(const V1_0::Request& request); 300 bool compliantWithV1_0(const V1_3::Request& request); 301 bool compliantWithV1_2(const V1_3::Request& request); 302 303 V1_0::Request convertToV1_0(const V1_0::Request& request); 304 V1_0::Request convertToV1_0(const V1_3::Request& request); 305 V1_0::Request convertToV1_2(const V1_3::Request& request); 306 V1_3::Request convertToV1_3(const V1_0::Request& request); 307 V1_3::Request convertToV1_3(const V1_3::Request& request); 308 309 bool compliantWithV1_0(V1_0::OperandLifeTime lifetime); 310 bool compliantWithV1_0(V1_3::OperandLifeTime lifetime); 311 bool compliantWithV1_3(V1_0::OperandLifeTime lifetime); 312 bool compliantWithV1_3(V1_3::OperandLifeTime lifetime); 313 314 V1_0::OperandLifeTime convertToV1_0(V1_0::OperandLifeTime lifetime); 315 V1_0::OperandLifeTime convertToV1_0(V1_3::OperandLifeTime lifetime); 316 V1_3::OperandLifeTime convertToV1_3(V1_0::OperandLifeTime lifetime); 317 V1_3::OperandLifeTime convertToV1_3(V1_3::OperandLifeTime lifetime); 318 319 constexpr V1_3::Priority convertToHalPriority(int32_t priority) { 320 switch (priority) { 321 case ANEURALNETWORKS_PRIORITY_LOW: 322 return V1_3::Priority::LOW; 323 case ANEURALNETWORKS_PRIORITY_MEDIUM: 324 return V1_3::Priority::MEDIUM; 325 case ANEURALNETWORKS_PRIORITY_HIGH: 326 return V1_3::Priority::HIGH; 327 } 328 LOG(FATAL) << "unrecognized priority: " << priority; 329 return {}; 330 } 331 332 // DEPRECATED. Use checked conversions from nnapi/hal/1.X/Conversions.h. 333 Capabilities::OperandPerformance uncheckedConvert( 334 const V1_3::Capabilities::OperandPerformance& operandPerformance); 335 Capabilities::PerformanceInfo uncheckedConvert(const V1_0::PerformanceInfo& performanceInfo); 336 Capabilities uncheckedConvert(const V1_3::Capabilities& capabilities); 337 DataLocation uncheckedConvert(const V1_0::DataLocation& location); 338 ErrorStatus uncheckedConvert(V1_0::ErrorStatus status); 339 ErrorStatus uncheckedConvert(V1_3::ErrorStatus status); 340 Extension::OperandTypeInformation uncheckedConvert(const V1_2::Extension::OperandTypeInformation&); 341 Extension uncheckedConvert(const V1_2::Extension& extension); 342 hardware::hidl_vec<uint8_t> uncheckedConvert(const Operand::ExtensionParams& params); 343 MeasureTiming uncheckedConvert(V1_2::MeasureTiming measure); 344 SharedMemory uncheckedConvert(const hardware::hidl_memory& memory); 345 ExtensionNameAndPrefix uncheckedConvert(const V1_2::Model::ExtensionNameAndPrefix&); 346 Model::Subgraph uncheckedConvert(const V1_3::Subgraph& subgraph); 347 Model uncheckedConvert(const V1_3::Model& model); 348 Operand::ExtensionParams uncheckedConvert(const hardware::hidl_vec<uint8_t>& params); 349 Operand::ExtraParams uncheckedConvert(const V1_2::Operand::ExtraParams& params); 350 Operand::LifeTime uncheckedConvert(V1_3::OperandLifeTime lifetime); 351 Operand::SymmPerChannelQuantParams uncheckedConvert(const V1_2::SymmPerChannelQuantParams& params); 352 OperandType uncheckedConvert(V1_3::OperandType operandType); 353 Operand uncheckedConvert(const V1_3::Operand& operand); 354 OperationType uncheckedConvert(V1_3::OperationType operationType); 355 Operation uncheckedConvert(const V1_3::Operation& operation); 356 OptionalDuration uncheckedConvert(const V1_3::OptionalTimeoutDuration& timeoutDuration); 357 OutputShape uncheckedConvert(const V1_2::OutputShape& outputShape); 358 Request::Argument uncheckedConvert(const V1_0::RequestArgument& requestArgument); 359 Request::MemoryPool uncheckedConvert(const V1_3::Request::MemoryPool& memoryPool); 360 Request uncheckedConvert(const V1_3::Request& request); 361 std::vector<Extension> uncheckedConvert(const hardware::hidl_vec<V1_2::Extension>& extensions); 362 std::vector<SharedMemory> uncheckedConvert( 363 const hardware::hidl_vec<hardware::hidl_memory>& memories); 364 std::vector<Model::Subgraph> uncheckedConvert(const hardware::hidl_vec<V1_3::Subgraph>& subgraphs); 365 std::vector<Operand> uncheckedConvert(const hardware::hidl_vec<V1_3::Operand>& operands); 366 std::vector<OutputShape> uncheckedConvert( 367 const hardware::hidl_vec<V1_2::OutputShape>& outputShapes); 368 std::vector<Request::MemoryPool> uncheckedConvert( 369 const hardware::hidl_vec<V1_3::Request::MemoryPool>& memoryPools); 370 Timing uncheckedConvert(const V1_2::Timing& timing); 371 372 // DEPRECATED. Use conversions from nnapi/hal/1.X/Conversions.h. 373 hardware::hidl_memory convertToV1_0(const SharedMemory& memory); 374 hardware::hidl_vec<hardware::hidl_memory> convertToV1_0(const std::vector<SharedMemory>& memories); 375 hardware::hidl_vec<uint8_t> convertToV1_0(const Model::OperandValues& operandValues); 376 hardware::hidl_vec<V1_2::OutputShape> convertToV1_2(const std::vector<OutputShape>& outputShapes); 377 hardware::hidl_vec<V1_3::BufferRole> convertToV1_3(const std::vector<BufferRole>& bufferRoles); 378 V1_0::DataLocation convertToV1_0(const DataLocation& location); 379 V1_0::ErrorStatus convertToV1_0(ErrorStatus status); 380 V1_0::RequestArgument convertToV1_0(const Request::Argument& requestArgument); 381 V1_1::ExecutionPreference convertToV1_1(ExecutionPreference preference); 382 V1_2::MeasureTiming convertToV1_2(MeasureTiming measure); 383 V1_2::Model::ExtensionNameAndPrefix convertToV1_2(const ExtensionNameAndPrefix&); 384 V1_2::Operand::ExtraParams convertToV1_2(const Operand::ExtraParams& params); 385 V1_2::OutputShape convertToV1_2(const OutputShape& outputShape); 386 V1_2::SymmPerChannelQuantParams convertToV1_2(const Operand::SymmPerChannelQuantParams& params); 387 V1_2::Timing convertToV1_2(const Timing& timing); 388 V1_3::BufferRole convertToV1_3(const BufferRole& bufferRole); 389 V1_3::ErrorStatus convertToV1_3(ErrorStatus status); 390 V1_3::Model convertToV1_3(const Model& model); 391 V1_3::Operand convertToV1_3(const Operand& operand); 392 V1_3::OperandLifeTime convertToV1_3(Operand::LifeTime lifetime); 393 V1_3::OperandType convertToV1_3(OperandType operandType); 394 V1_3::Operation convertToV1_3(const Operation& operation); 395 V1_3::OperationType convertToV1_3(OperationType operationType); 396 V1_3::OptionalTimeoutDuration convertToV1_3(const OptionalDuration& timeoutDuration); 397 V1_3::OptionalTimePoint convertToV1_3(const OptionalTimePoint& timePoint); 398 V1_3::Priority convertToV1_3(Priority priority); 399 V1_3::Request convertToV1_3(const Request& request); 400 V1_3::Request::MemoryPool convertToV1_3(const Request::MemoryPool& memoryPool); 401 V1_3::Subgraph convertToV1_3(const Model::Subgraph& model); 402 403 } // namespace nn 404 } // namespace android 405 406 #endif // ANDROID_PACKAGES_MODULES_NEURALNETWORKS_COMMON_LEGACY_HAL_UTILS_H 407