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 
17 #define LOG_TAG "Utils"
18 
19 #include "LegacyHalUtils.h"
20 
21 #include <nnapi/TypeUtils.h>
22 #include <nnapi/hal/1.0/Conversions.h>
23 #include <nnapi/hal/1.1/Conversions.h>
24 #include <nnapi/hal/1.2/Conversions.h>
25 #include <nnapi/hal/1.3/Conversions.h>
26 #include <nnapi/hal/aidl/Conversions.h>
27 
28 #include <algorithm>
29 #include <limits>
30 #include <set>
31 #include <string>
32 #include <tuple>
33 #include <type_traits>
34 #include <utility>
35 #include <vector>
36 
37 #include "CpuExecutor.h"
38 #include "NeuralNetworks.h"
39 #include "ValidateHal.h"
40 
41 namespace android {
42 namespace nn {
43 
44 constexpr V1_0::PerformanceInfo kNoPerformanceInfo = {.execTime = FLT_MAX, .powerUsage = FLT_MAX};
45 
46 template <typename Type>
handleError(GeneralResult<Type> result)47 static Type handleError(GeneralResult<Type> result) {
48     CHECK(result.has_value()) << "Unhandled error (" << result.error().code
49                               << "): " << result.error().message;
50     return std::move(result).value();
51 }
52 
makeDeadline(const V1_3::OptionalTimePoint & timePoint)53 LegacyOptionalTimePoint makeDeadline(const V1_3::OptionalTimePoint& timePoint) {
54     using Disc = V1_3::OptionalTimePoint::hidl_discriminator;
55     if (timePoint.getDiscriminator() == Disc::none) {
56         return LegacyOptionalTimePoint{};
57     }
58     const uint64_t count = timePoint.nanosecondsSinceEpoch();
59     return LegacyTimePoint{LegacyDuration{count}};
60 }
61 
makeDeadline(const V1_3::OptionalTimeoutDuration & optionalDuration)62 LegacyOptionalTimePoint makeDeadline(const V1_3::OptionalTimeoutDuration& optionalDuration) {
63     if (optionalDuration.getDiscriminator() ==
64         V1_3::OptionalTimeoutDuration::hidl_discriminator::none) {
65         return LegacyOptionalTimePoint{};
66     }
67 
68     const auto duration = LegacyDuration{optionalDuration.nanoseconds()};
69     constexpr auto kMaxTime = LegacyTimePoint::max();
70     const auto currentTime = LegacyClock::now();
71 
72     // If there would be an overflow, use the max value.
73     if (duration > kMaxTime - currentTime) {
74         return kMaxTime;
75     }
76     return currentTime + duration;
77 }
78 
hasDeadlinePassed(const LegacyOptionalTimePoint & deadline)79 bool hasDeadlinePassed(const LegacyOptionalTimePoint& deadline) {
80     if (!deadline.has_value()) {
81         return false;
82     }
83     return LegacyClock::now() >= *deadline;
84 }
85 
isExtensionOperandType(V1_3::OperandType type)86 bool isExtensionOperandType(V1_3::OperandType type) {
87     return isExtensionOperandType(static_cast<OperandType>(type));
88 }
89 
isExtensionOperationType(V1_3::OperationType type)90 bool isExtensionOperationType(V1_3::OperationType type) {
91     return isExtensionOperationType(static_cast<OperationType>(type));
92 }
93 
getOperandTypeName(V1_3::OperandType type)94 std::string getOperandTypeName(V1_3::OperandType type) {
95     return toString(type);
96 }
97 
getOperationName(V1_3::OperationType type)98 std::string getOperationName(V1_3::OperationType type) {
99     return toString(type);
100 }
101 
nonExtensionOperandSizeOfData(V1_3::OperandType type,const std::vector<uint32_t> & dimensions)102 uint32_t nonExtensionOperandSizeOfData(V1_3::OperandType type,
103                                        const std::vector<uint32_t>& dimensions) {
104     return nonExtensionOperandSizeOfData(uncheckedConvert(type), dimensions);
105 }
106 
nonExtensionOperandSizeOfDataOverflowsUInt32(V1_3::OperandType type,const std::vector<uint32_t> & dimensions)107 bool nonExtensionOperandSizeOfDataOverflowsUInt32(V1_3::OperandType type,
108                                                   const std::vector<uint32_t>& dimensions) {
109     return nonExtensionOperandSizeOfDataOverflowsUInt32(uncheckedConvert(type), dimensions);
110 }
111 
tensorHasUnspecifiedDimensions(V1_3::OperandType type,const std::vector<uint32_t> & dimensions)112 bool tensorHasUnspecifiedDimensions(V1_3::OperandType type,
113                                     const std::vector<uint32_t>& dimensions) {
114     return tensorHasUnspecifiedDimensions(static_cast<int>(type), dimensions.data(),
115                                           dimensions.size());
116 }
117 
tensorHasUnspecifiedDimensions(const V1_3::Operand & operand)118 bool tensorHasUnspecifiedDimensions(const V1_3::Operand& operand) {
119     return tensorHasUnspecifiedDimensions(static_cast<int>(operand.type), operand.dimensions.data(),
120                                           operand.dimensions.size());
121 }
122 
logModelToInfo(const V1_0::Model & model)123 void logModelToInfo(const V1_0::Model& model) {
124     LOG(INFO) << "V1_0::Model start";
125     LOG(INFO) << "operands" << toString(model.operands);
126     LOG(INFO) << "operations" << toString(model.operations);
127     LOG(INFO) << "inputIndexes" << toString(model.inputIndexes);
128     LOG(INFO) << "outputIndexes" << toString(model.outputIndexes);
129     LOG(INFO) << "operandValues size" << model.operandValues.size();
130     LOG(INFO) << "pools" << SHOW_IF_DEBUG(toString(model.pools));
131 }
132 
logModelToInfo(const V1_1::Model & model)133 void logModelToInfo(const V1_1::Model& model) {
134     LOG(INFO) << "V1_1::Model start";
135     LOG(INFO) << "operands" << toString(model.operands);
136     LOG(INFO) << "operations" << toString(model.operations);
137     LOG(INFO) << "inputIndexes" << toString(model.inputIndexes);
138     LOG(INFO) << "outputIndexes" << toString(model.outputIndexes);
139     LOG(INFO) << "operandValues size " << model.operandValues.size();
140     LOG(INFO) << "pools" << SHOW_IF_DEBUG(toString(model.pools));
141 }
142 
logModelToInfo(const V1_2::Model & model)143 void logModelToInfo(const V1_2::Model& model) {
144     LOG(INFO) << "V1_2::Model start";
145     LOG(INFO) << "operands" << toString(model.operands);
146     LOG(INFO) << "operations" << toString(model.operations);
147     LOG(INFO) << "inputIndexes" << toString(model.inputIndexes);
148     LOG(INFO) << "outputIndexes" << toString(model.outputIndexes);
149     LOG(INFO) << "operandValues size" << model.operandValues.size();
150     LOG(INFO) << "pools" << SHOW_IF_DEBUG(toString(model.pools));
151     LOG(INFO) << "relaxComputationFloat32toFloat16" << model.relaxComputationFloat32toFloat16;
152     LOG(INFO) << "extensionNameToPrefix" << toString(model.extensionNameToPrefix);
153 }
154 
logSubgraphToInfo(std::string label,const V1_3::Subgraph & subgraph)155 static void logSubgraphToInfo(std::string label, const V1_3::Subgraph& subgraph) {
156     LOG(INFO) << label << ".operands" << toString(subgraph.operands);
157     LOG(INFO) << label << ".operations" << toString(subgraph.operations);
158     LOG(INFO) << label << ".inputIndexes" << toString(subgraph.inputIndexes);
159     LOG(INFO) << label << ".outputIndexes" << toString(subgraph.outputIndexes);
160 }
161 
logModelToInfo(const V1_3::Model & model)162 void logModelToInfo(const V1_3::Model& model) {
163     LOG(INFO) << "V1_3::Model start";
164     logSubgraphToInfo("main", model.main);
165     for (uint32_t i = 0, n = model.referenced.size(); i < n; ++i) {
166         logSubgraphToInfo("referenced[" + std::to_string(i) + "]", model.referenced[i]);
167     }
168     LOG(INFO) << "operandValues size " << model.operandValues.size();
169     LOG(INFO) << "pools" << SHOW_IF_DEBUG(toString(model.pools));
170     LOG(INFO) << "relaxComputationFloat32toFloat16 " << model.relaxComputationFloat32toFloat16;
171     LOG(INFO) << "extensionNameToPrefix" << toString(model.extensionNameToPrefix);
172 }
173 
validateOperandSymmPerChannelQuantParams(const V1_3::Operand & halOperand,const ANeuralNetworksSymmPerChannelQuantParams & channelQuant,const char * tag)174 bool validateOperandSymmPerChannelQuantParams(
175         const V1_3::Operand& halOperand,
176         const ANeuralNetworksSymmPerChannelQuantParams& channelQuant, const char* tag) {
177     if (halOperand.type != V1_3::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL) {
178         return false;
179     }
180 
181     NN_RET_CHECK_LT(channelQuant.channelDim, halOperand.dimensions.size()) << tag;
182     NN_RET_CHECK(channelQuant.scales != nullptr) << tag;
183     NN_RET_CHECK_EQ(channelQuant.scaleCount, halOperand.dimensions[channelQuant.channelDim]) << tag;
184     NN_RET_CHECK_NE(halOperand.dimensions[channelQuant.channelDim], 0u)
185             << tag << " channel dimension " << channelQuant.channelDim << " is underspecified";
186     for (uint32_t i = 0; i < halOperand.dimensions[channelQuant.channelDim]; i++) {
187         NN_RET_CHECK_GT(channelQuant.scales[i], 0.0f) << tag << " invalid scaleArray[" << i << "]";
188     }
189     return true;
190 }
191 
validateHalVersion(ANeuralNetworksOperationType opType,HalVersion halVersion,HalVersion minSupportedHalVersion)192 static int validateHalVersion(ANeuralNetworksOperationType opType, HalVersion halVersion,
193                               HalVersion minSupportedHalVersion) {
194     if (halVersion < minSupportedHalVersion) {
195         LOG(ERROR) << "The given inputs and outputs for operation " << opType
196                    << " are only supported in " << minSupportedHalVersion
197                    << " and later (validating using " << halVersion << ")";
198         return ANEURALNETWORKS_BAD_DATA;
199     }
200     return ANEURALNETWORKS_NO_ERROR;
201 }
202 
validateOperation(ANeuralNetworksOperationType opType,uint32_t inputCount,const uint32_t * inputIndexes,uint32_t outputCount,const uint32_t * outputIndexes,const std::vector<Operand> & operands,HalVersion halVersion)203 static inline int validateOperation(ANeuralNetworksOperationType opType, uint32_t inputCount,
204                                     const uint32_t* inputIndexes, uint32_t outputCount,
205                                     const uint32_t* outputIndexes,
206                                     const std::vector<Operand>& operands, HalVersion halVersion) {
207     if (opType == ANEURALNETWORKS_IF || opType == ANEURALNETWORKS_WHILE) {
208         NN_RETURN_IF_ERROR(validateHalVersion(opType, halVersion, HalVersion::V1_3));
209         LOG(ERROR) << "This validateOperation() overload does not support control flow";
210         return ANEURALNETWORKS_BAD_DATA;
211     }
212     return validateOperation(opType, inputCount, inputIndexes, outputCount, outputIndexes, operands,
213                              halVersion, {});
214 }
215 
convertResultCodeToHalErrorStatus(int resultCode)216 V1_3::ErrorStatus convertResultCodeToHalErrorStatus(int resultCode) {
217     return convertToV1_3(convertResultCodeToErrorStatus(resultCode));
218 }
219 
convertErrorStatusToResultCode(V1_3::ErrorStatus status)220 int convertErrorStatusToResultCode(V1_3::ErrorStatus status) {
221     return convertErrorStatusToResultCode(uncheckedConvert(status));
222 }
223 
getExecutionResult(V1_3::ErrorStatus status,const hardware::hidl_vec<V1_2::OutputShape> & outputShapes,const V1_2::Timing & timing)224 std::tuple<int, std::vector<OutputShape>, Timing> getExecutionResult(
225         V1_3::ErrorStatus status, const hardware::hidl_vec<V1_2::OutputShape>& outputShapes,
226         const V1_2::Timing& timing) {
227     return getExecutionResult(uncheckedConvert(status), uncheckedConvert(outputShapes),
228                               uncheckedConvert(timing));
229 }
230 
231 // Capabilities::operandPerformance utilities.
232 // The field Capabilities::operandPerformance is a vector sorted by the field
233 // Capabilities::OperandPerformance::type.
234 
235 template <HalVersion version>
nonExtensionOperandPerformance(V1_0::PerformanceInfo perf)236 hardware::hidl_vec<VersionedOperandPerformance<version>> nonExtensionOperandPerformance(
237         V1_0::PerformanceInfo perf) {
238     using OpPerf = VersionedOperandPerformance<version>;
239 
240     // Note: range presents enumerators in declaration order, not in numerical order.
241     static constexpr hardware::hidl_enum_range<VersionedOperandType<version>> kOperandTypeRange;
242 
243     std::vector<OpPerf> ret;
244     ret.reserve(kOperandTypeRange.end() - kOperandTypeRange.begin());
245     for (VersionedOperandType<version> type : kOperandTypeRange) {
246         if (static_cast<V1_3::OperandType>(type) != V1_3::OperandType::SUBGRAPH) {
247             ret.push_back(OpPerf{type, perf});
248         }
249     }
250     std::sort(ret.begin(), ret.end(),
251               [](const OpPerf& a, const OpPerf& b) { return a.type < b.type; });
252 
253     return ret;
254 }
255 
256 template hardware::hidl_vec<V1_2::Capabilities::OperandPerformance>
257 nonExtensionOperandPerformance<HalVersion::V1_2>(V1_0::PerformanceInfo perf);
258 template hardware::hidl_vec<V1_3::Capabilities::OperandPerformance>
259 nonExtensionOperandPerformance<HalVersion::V1_3>(V1_0::PerformanceInfo perf);
260 
261 template <HalVersion version>
update(hardware::hidl_vec<VersionedOperandPerformance<version>> * operandPerformance,VersionedOperandType<version> type,V1_0::PerformanceInfo perf)262 void update(hardware::hidl_vec<VersionedOperandPerformance<version>>* operandPerformance,
263             VersionedOperandType<version> type, V1_0::PerformanceInfo perf) {
264     CHECK(operandPerformance != nullptr);
265     const auto it =
266             std::lower_bound(operandPerformance->begin(), operandPerformance->end(), type,
267                              [](const VersionedOperandPerformance<version>& perf,
268                                 VersionedOperandType<version> type) { return perf.type < type; });
269     CHECK(it != operandPerformance->end())
270             << toString(type) << " not in " << toString(*operandPerformance);
271     it->info = perf;
272 }
273 
update(hardware::hidl_vec<V1_2::Capabilities::OperandPerformance> * operandPerformance,V1_2::OperandType type,V1_0::PerformanceInfo perf)274 void update(hardware::hidl_vec<V1_2::Capabilities::OperandPerformance>* operandPerformance,
275             V1_2::OperandType type, V1_0::PerformanceInfo perf) {
276     update<HalVersion::V1_2>(operandPerformance, type, perf);
277 }
update(hardware::hidl_vec<V1_3::Capabilities::OperandPerformance> * operandPerformance,V1_3::OperandType type,V1_0::PerformanceInfo perf)278 void update(hardware::hidl_vec<V1_3::Capabilities::OperandPerformance>* operandPerformance,
279             V1_3::OperandType type, V1_0::PerformanceInfo perf) {
280     update<HalVersion::V1_3>(operandPerformance, type, perf);
281 }
282 
283 template <HalVersion version>
lookup(const hardware::hidl_vec<VersionedOperandPerformance<version>> & operandPerformance,VersionedOperandType<version> type)284 V1_0::PerformanceInfo lookup(
285         const hardware::hidl_vec<VersionedOperandPerformance<version>>& operandPerformance,
286         VersionedOperandType<version> type) {
287     const auto it = std::lower_bound(operandPerformance.begin(), operandPerformance.end(), type,
288                                      [](const VersionedOperandPerformance<version>& perf,
289                                         VersionedOperandType<version> type) {
290                                          return static_cast<V1_3::OperandType>(perf.type) <
291                                                 static_cast<V1_3::OperandType>(type);
292                                      });
293     if (it == operandPerformance.end()) {
294         LOG(WARNING) << "No PerformanceInfo for " << toString(type);
295         return kNoPerformanceInfo;
296     } else {
297         return it->info;
298     }
299 }
300 
lookup(const hardware::hidl_vec<V1_2::Capabilities::OperandPerformance> & operandPerformance,V1_2::OperandType type)301 V1_0::PerformanceInfo lookup(
302         const hardware::hidl_vec<V1_2::Capabilities::OperandPerformance>& operandPerformance,
303         V1_2::OperandType type) {
304     return lookup<HalVersion::V1_2>(operandPerformance, type);
305 }
lookup(const hardware::hidl_vec<V1_3::Capabilities::OperandPerformance> & operandPerformance,V1_3::OperandType type)306 V1_0::PerformanceInfo lookup(
307         const hardware::hidl_vec<V1_3::Capabilities::OperandPerformance>& operandPerformance,
308         V1_3::OperandType type) {
309     CHECK(type != V1_3::OperandType::SUBGRAPH)
310             << "Use Capabilities::ifPerformance or Capabilities::whilePerformance";
311     return lookup<HalVersion::V1_3>(operandPerformance, type);
312 }
313 
setRunTimePoolInfosFromHidlMemories(std::vector<RunTimePoolInfo> * poolInfos,const hardware::hidl_vec<hardware::hidl_memory> & pools)314 bool setRunTimePoolInfosFromHidlMemories(std::vector<RunTimePoolInfo>* poolInfos,
315                                          const hardware::hidl_vec<hardware::hidl_memory>& pools) {
316     return setRunTimePoolInfosFromCanonicalMemories(poolInfos, uncheckedConvert(pools));
317 }
318 
319 // Versioning
320 
321 // In Android P, most data types are treated as having the same performance as TENSOR_QUANT8_ASYMM.
322 // This array must be in sorted order.
323 static const V1_3::OperandType kQuantized8PerformanceConsistentWithP[] = {
324         V1_3::OperandType::INT32, V1_3::OperandType::UINT32, V1_3::OperandType::TENSOR_INT32,
325         V1_3::OperandType::OEM, V1_3::OperandType::TENSOR_OEM_BYTE};
326 
isQuantized8PerformanceConsistentWithP(const V1_2::Capabilities & capabilities)327 static bool isQuantized8PerformanceConsistentWithP(const V1_2::Capabilities& capabilities) {
328     const V1_0::PerformanceInfo quantized8Performance =
329             lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_QUANT8_ASYMM);
330     return std::all_of(std::begin(kQuantized8PerformanceConsistentWithP),
331                        std::end(kQuantized8PerformanceConsistentWithP),
332                        [quantized8Performance, &capabilities](V1_3::OperandType type) {
333                            return quantized8Performance ==
334                                   lookup(capabilities.operandPerformance,
335                                          static_cast<V1_2::OperandType>(type));
336                        });
337 }
338 
isQuantized8PerformanceConsistentWithP(const V1_3::Capabilities & capabilities)339 static bool isQuantized8PerformanceConsistentWithP(const V1_3::Capabilities& capabilities) {
340     const V1_0::PerformanceInfo quantized8Performance =
341             lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM);
342     return std::all_of(std::begin(kQuantized8PerformanceConsistentWithP),
343                        std::end(kQuantized8PerformanceConsistentWithP),
344                        [quantized8Performance, &capabilities](V1_3::OperandType type) {
345                            return quantized8Performance ==
346                                   lookup(capabilities.operandPerformance, type);
347                        });
348 }
349 
350 static hardware::hidl_vec<V1_2::Capabilities::OperandPerformance>
makeQuantized8PerformanceConsistentWithP(V1_0::PerformanceInfo quantized8Performance)351 makeQuantized8PerformanceConsistentWithP(V1_0::PerformanceInfo quantized8Performance) {
352     hardware::hidl_vec<V1_2::Capabilities::OperandPerformance> ret(
353             std::size(kQuantized8PerformanceConsistentWithP));
354     std::transform(std::begin(kQuantized8PerformanceConsistentWithP),
355                    std::end(kQuantized8PerformanceConsistentWithP), ret.begin(),
356                    [quantized8Performance](
357                            V1_3::OperandType type) -> V1_2::Capabilities::OperandPerformance {
358                        return {static_cast<V1_2::OperandType>(type), quantized8Performance};
359                    });
360     return ret;
361 }
362 
compliantWithV1_0(const V1_0::Capabilities &)363 bool compliantWithV1_0(const V1_0::Capabilities&) {
364     return true;
365 }
366 
compliantWithV1_0(const V1_1::Capabilities & capabilities)367 bool compliantWithV1_0(const V1_1::Capabilities& capabilities) {
368     return capabilities.relaxedFloat32toFloat16Performance == capabilities.float32Performance;
369 }
370 
compliantWithV1_0(const V1_2::Capabilities & capabilities)371 bool compliantWithV1_0(const V1_2::Capabilities& capabilities) {
372     const V1_0::PerformanceInfo perfTensorFloat32 =
373             lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_FLOAT32);
374     const V1_0::PerformanceInfo perfFloat32 =
375             lookup(capabilities.operandPerformance, V1_2::OperandType::FLOAT32);
376     if (perfTensorFloat32 != perfFloat32 ||
377         perfTensorFloat32 != capabilities.relaxedFloat32toFloat16PerformanceTensor ||
378         perfFloat32 != capabilities.relaxedFloat32toFloat16PerformanceScalar) {
379         return false;
380     }
381 
382     return isQuantized8PerformanceConsistentWithP(capabilities);
383 }
384 
compliantWithV1_0(const V1_3::Capabilities & capabilities)385 bool compliantWithV1_0(const V1_3::Capabilities& capabilities) {
386     const V1_0::PerformanceInfo perfTensorFloat32 =
387             lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32);
388     const V1_0::PerformanceInfo perfFloat32 =
389             lookup(capabilities.operandPerformance, V1_3::OperandType::FLOAT32);
390     if (perfTensorFloat32 != perfFloat32 ||
391         perfTensorFloat32 != capabilities.relaxedFloat32toFloat16PerformanceTensor ||
392         perfFloat32 != capabilities.relaxedFloat32toFloat16PerformanceScalar) {
393         return false;
394     }
395 
396     return isQuantized8PerformanceConsistentWithP(capabilities);
397 }
398 
compliantWithV1_1(const V1_0::Capabilities &)399 bool compliantWithV1_1(const V1_0::Capabilities&) {
400     return true;
401 }
402 
compliantWithV1_1(const V1_1::Capabilities &)403 bool compliantWithV1_1(const V1_1::Capabilities&) {
404     return true;
405 }
406 
compliantWithV1_1(const V1_2::Capabilities & capabilities)407 bool compliantWithV1_1(const V1_2::Capabilities& capabilities) {
408     if ((capabilities.relaxedFloat32toFloat16PerformanceTensor !=
409          capabilities.relaxedFloat32toFloat16PerformanceScalar) ||
410         (lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_FLOAT32) !=
411          lookup(capabilities.operandPerformance, V1_2::OperandType::FLOAT32))) {
412         return false;
413     }
414 
415     return isQuantized8PerformanceConsistentWithP(capabilities);
416 }
417 
compliantWithV1_1(const V1_3::Capabilities & capabilities)418 bool compliantWithV1_1(const V1_3::Capabilities& capabilities) {
419     if ((capabilities.relaxedFloat32toFloat16PerformanceTensor !=
420          capabilities.relaxedFloat32toFloat16PerformanceScalar) ||
421         (lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32) !=
422          lookup(capabilities.operandPerformance, V1_3::OperandType::FLOAT32))) {
423         return false;
424     }
425 
426     return isQuantized8PerformanceConsistentWithP(capabilities);
427 }
428 
compliantWithV1_2(const V1_0::Capabilities &)429 bool compliantWithV1_2(const V1_0::Capabilities&) {
430     return true;
431 }
432 
compliantWithV1_2(const V1_1::Capabilities &)433 bool compliantWithV1_2(const V1_1::Capabilities&) {
434     return true;
435 }
436 
compliantWithV1_2(const V1_2::Capabilities &)437 bool compliantWithV1_2(const V1_2::Capabilities&) {
438     return true;
439 }
440 
compliantWithV1_2(const V1_3::Capabilities &)441 bool compliantWithV1_2(const V1_3::Capabilities&) {
442     return true;
443 }
444 
compliantWithV1_3(const V1_0::Capabilities &)445 bool compliantWithV1_3(const V1_0::Capabilities&) {
446     return true;
447 }
448 
compliantWithV1_3(const V1_1::Capabilities &)449 bool compliantWithV1_3(const V1_1::Capabilities&) {
450     return true;
451 }
452 
compliantWithV1_3(const V1_2::Capabilities &)453 bool compliantWithV1_3(const V1_2::Capabilities&) {
454     return true;
455 }
456 
compliantWithV1_3(const V1_3::Capabilities &)457 bool compliantWithV1_3(const V1_3::Capabilities&) {
458     return true;
459 }
460 
convertToV1_0(V1_0::ErrorStatus status)461 V1_0::ErrorStatus convertToV1_0(V1_0::ErrorStatus status) {
462     return status;
463 }
464 
convertToV1_0(V1_3::ErrorStatus status)465 V1_0::ErrorStatus convertToV1_0(V1_3::ErrorStatus status) {
466     switch (status) {
467         case V1_3::ErrorStatus::NONE:
468             return V1_0::ErrorStatus::NONE;
469         case V1_3::ErrorStatus::DEVICE_UNAVAILABLE:
470             return V1_0::ErrorStatus::DEVICE_UNAVAILABLE;
471         case V1_3::ErrorStatus::GENERAL_FAILURE:
472             return V1_0::ErrorStatus::GENERAL_FAILURE;
473         case V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
474             return V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
475         case V1_3::ErrorStatus::INVALID_ARGUMENT:
476             return V1_0::ErrorStatus::INVALID_ARGUMENT;
477         case V1_3::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
478             return V1_0::ErrorStatus::GENERAL_FAILURE;
479         case V1_3::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
480             return V1_0::ErrorStatus::GENERAL_FAILURE;
481         case V1_3::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
482             return V1_0::ErrorStatus::GENERAL_FAILURE;
483         case V1_3::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
484             return V1_0::ErrorStatus::GENERAL_FAILURE;
485     }
486     LOG(ERROR) << "Unknown ErrorStatus: " << toString(status) << " mapped to GENERAL_FAILURE";
487     return V1_0::ErrorStatus::GENERAL_FAILURE;
488 }
489 
convertToV1_3(V1_0::ErrorStatus status)490 V1_3::ErrorStatus convertToV1_3(V1_0::ErrorStatus status) {
491     return static_cast<V1_3::ErrorStatus>(status);
492 }
493 
convertToV1_3(V1_3::ErrorStatus status)494 V1_3::ErrorStatus convertToV1_3(V1_3::ErrorStatus status) {
495     return status;
496 }
497 
uncheckedConvertToV1_0(V1_1::OperationType type)498 static V1_0::OperationType uncheckedConvertToV1_0(V1_1::OperationType type) {
499     return static_cast<V1_0::OperationType>(type);
500 }
501 
uncheckedConvertToV1_0(V1_2::OperationType type)502 static V1_0::OperationType uncheckedConvertToV1_0(V1_2::OperationType type) {
503     return static_cast<V1_0::OperationType>(type);
504 }
505 
uncheckedConvertToV1_0(V1_3::OperationType type)506 V1_0::OperationType uncheckedConvertToV1_0(V1_3::OperationType type) {
507     return static_cast<V1_0::OperationType>(type);
508 }
509 
convertToV1_1(V1_0::OperationType type)510 static V1_1::OperationType convertToV1_1(V1_0::OperationType type) {
511     return static_cast<V1_1::OperationType>(type);
512 }
513 
uncheckedConvertToV1_1(V1_2::OperationType type)514 static V1_1::OperationType uncheckedConvertToV1_1(V1_2::OperationType type) {
515     return static_cast<V1_1::OperationType>(type);
516 }
517 
uncheckedConvertToV1_1(V1_3::OperationType type)518 V1_1::OperationType uncheckedConvertToV1_1(V1_3::OperationType type) {
519     return static_cast<V1_1::OperationType>(type);
520 }
521 
convertToV1_2(V1_0::OperationType type)522 static V1_2::OperationType convertToV1_2(V1_0::OperationType type) {
523     return static_cast<V1_2::OperationType>(type);
524 }
525 
convertToV1_2(V1_1::OperationType type)526 static V1_2::OperationType convertToV1_2(V1_1::OperationType type) {
527     return static_cast<V1_2::OperationType>(type);
528 }
529 
uncheckedConvertToV1_2(V1_3::OperationType type)530 V1_2::OperationType uncheckedConvertToV1_2(V1_3::OperationType type) {
531     return static_cast<V1_2::OperationType>(type);
532 }
533 
convertToV1_3(V1_0::OperationType type)534 static V1_3::OperationType convertToV1_3(V1_0::OperationType type) {
535     return static_cast<V1_3::OperationType>(type);
536 }
537 
convertToV1_3(V1_1::OperationType type)538 static V1_3::OperationType convertToV1_3(V1_1::OperationType type) {
539     return static_cast<V1_3::OperationType>(type);
540 }
541 
convertToV1_3(V1_2::OperationType type)542 static V1_3::OperationType convertToV1_3(V1_2::OperationType type) {
543     return static_cast<V1_3::OperationType>(type);
544 }
545 
convertToV1_0(const V1_0::Capabilities & capabilities)546 V1_0::Capabilities convertToV1_0(const V1_0::Capabilities& capabilities) {
547     return capabilities;
548 }
549 
convertToV1_0(const V1_1::Capabilities & capabilities)550 V1_0::Capabilities convertToV1_0(const V1_1::Capabilities& capabilities) {
551     if (!compliantWithV1_0(capabilities)) {
552         LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities)
553                    << " from V1_1::Capabilities to V1_0::Capabilities";
554     }
555     return {.float32Performance = capabilities.float32Performance,
556             .quantized8Performance = capabilities.quantized8Performance};
557 }
558 
convertToV1_0(const V1_2::Capabilities & capabilities)559 V1_0::Capabilities convertToV1_0(const V1_2::Capabilities& capabilities) {
560     if (!compliantWithV1_0(capabilities)) {
561         LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities)
562                    << " from V1_2::Capabilities to V1_0::Capabilities";
563     }
564     return {.float32Performance =
565                     lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_FLOAT32),
566             .quantized8Performance = lookup(capabilities.operandPerformance,
567                                             V1_2::OperandType::TENSOR_QUANT8_ASYMM)};
568 }
569 
convertToV1_0(const V1_3::Capabilities & capabilities)570 V1_0::Capabilities convertToV1_0(const V1_3::Capabilities& capabilities) {
571     if (!compliantWithV1_0(capabilities)) {
572         LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities)
573                    << " from V1_3::Capabilities to V1_0::Capabilities";
574     }
575     return {.float32Performance =
576                     lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32),
577             .quantized8Performance = lookup(capabilities.operandPerformance,
578                                             V1_3::OperandType::TENSOR_QUANT8_ASYMM)};
579 }
580 
convertToV1_1(const V1_0::Capabilities & capabilities)581 V1_1::Capabilities convertToV1_1(const V1_0::Capabilities& capabilities) {
582     return {.float32Performance = capabilities.float32Performance,
583             .quantized8Performance = capabilities.quantized8Performance,
584             .relaxedFloat32toFloat16Performance = capabilities.float32Performance};
585 }
586 
convertToV1_1(const V1_1::Capabilities & capabilities)587 V1_1::Capabilities convertToV1_1(const V1_1::Capabilities& capabilities) {
588     return capabilities;
589 }
590 
convertToV1_1(const V1_2::Capabilities & capabilities)591 V1_1::Capabilities convertToV1_1(const V1_2::Capabilities& capabilities) {
592     if (!compliantWithV1_1(capabilities)) {
593         LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities)
594                    << " from V1_2::Capabilities to V1_1::Capabilities";
595     }
596     return {.float32Performance =
597                     lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_FLOAT32),
598             .quantized8Performance =
599                     lookup(capabilities.operandPerformance, V1_2::OperandType::TENSOR_QUANT8_ASYMM),
600             .relaxedFloat32toFloat16Performance =
601                     capabilities.relaxedFloat32toFloat16PerformanceTensor};
602 }
603 
convertToV1_1(const V1_3::Capabilities & capabilities)604 V1_1::Capabilities convertToV1_1(const V1_3::Capabilities& capabilities) {
605     if (!compliantWithV1_1(capabilities)) {
606         LOG(ERROR) << "Upcasting non-compliant capabilities " << toString(capabilities)
607                    << " from V1_3::Capabilities to V1_1::Capabilities";
608     }
609     return {.float32Performance =
610                     lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32),
611             .quantized8Performance =
612                     lookup(capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM),
613             .relaxedFloat32toFloat16Performance =
614                     capabilities.relaxedFloat32toFloat16PerformanceTensor};
615 }
616 
convertToV1_2(const V1_0::Capabilities & capabilities)617 V1_2::Capabilities convertToV1_2(const V1_0::Capabilities& capabilities) {
618     V1_2::Capabilities ret = {
619             .relaxedFloat32toFloat16PerformanceScalar = capabilities.float32Performance,
620             .relaxedFloat32toFloat16PerformanceTensor = capabilities.float32Performance,
621             .operandPerformance =
622                     makeQuantized8PerformanceConsistentWithP(capabilities.quantized8Performance)};
623     auto& opPerf = ret.operandPerformance;
624     opPerf.resize(opPerf.size() + 2);
625     opPerf[opPerf.size() - 2] = {V1_2::OperandType::TENSOR_FLOAT32,
626                                  capabilities.float32Performance};
627     opPerf[opPerf.size() - 1] = {V1_2::OperandType::FLOAT32, capabilities.float32Performance};
628     using OperandPerformance = V1_2::Capabilities::OperandPerformance;
629     std::sort(opPerf.begin(), opPerf.end(),
630               [](const OperandPerformance& a, const OperandPerformance& b) {
631                   return a.type < b.type;
632               });
633     return ret;
634 }
635 
convertToV1_2(const V1_1::Capabilities & capabilities)636 V1_2::Capabilities convertToV1_2(const V1_1::Capabilities& capabilities) {
637     V1_2::Capabilities ret = {.relaxedFloat32toFloat16PerformanceScalar =
638                                       capabilities.relaxedFloat32toFloat16Performance,
639                               .relaxedFloat32toFloat16PerformanceTensor =
640                                       capabilities.relaxedFloat32toFloat16Performance,
641                               .operandPerformance = makeQuantized8PerformanceConsistentWithP(
642                                       capabilities.quantized8Performance)};
643     auto& opPerf = ret.operandPerformance;
644     opPerf.resize(opPerf.size() + 2);
645     opPerf[opPerf.size() - 2] = {V1_2::OperandType::TENSOR_FLOAT32,
646                                  capabilities.float32Performance};
647     opPerf[opPerf.size() - 1] = {V1_2::OperandType::FLOAT32, capabilities.float32Performance};
648     using OperandPerformance = V1_2::Capabilities::OperandPerformance;
649     std::sort(opPerf.begin(), opPerf.end(),
650               [](const OperandPerformance& a, const OperandPerformance& b) {
651                   return a.type < b.type;
652               });
653     return ret;
654 }
655 
convertToV1_2(const V1_2::Capabilities & capabilities)656 V1_2::Capabilities convertToV1_2(const V1_2::Capabilities& capabilities) {
657     return capabilities;
658 }
659 
convertToV1_2(const V1_3::Capabilities & capabilities)660 V1_2::Capabilities convertToV1_2(const V1_3::Capabilities& capabilities) {
661     V1_2::Capabilities ret = {
662             .relaxedFloat32toFloat16PerformanceScalar =
663                     capabilities.relaxedFloat32toFloat16PerformanceScalar,
664             .relaxedFloat32toFloat16PerformanceTensor =
665                     capabilities.relaxedFloat32toFloat16PerformanceTensor,
666     };
667     const auto& inputOpPerf = capabilities.operandPerformance;
668     hardware::hidl_vec<V1_3::Capabilities::OperandPerformance> opPerfSupported;
669     opPerfSupported.resize(inputOpPerf.size());
670     auto last =
671             std::copy_if(inputOpPerf.begin(), inputOpPerf.end(), opPerfSupported.begin(),
672                          [](V1_3::Capabilities::OperandPerformance opPerf) {
673                              return validOperandType(static_cast<V1_2::OperandType>(opPerf.type));
674                          });
675     opPerfSupported.resize(std::distance(opPerfSupported.begin(), last));
676 
677     auto& convertedOpPerf = ret.operandPerformance;
678     convertedOpPerf.resize(opPerfSupported.size());
679     std::transform(opPerfSupported.begin(), opPerfSupported.end(), convertedOpPerf.begin(),
680                    [](V1_3::Capabilities::OperandPerformance opPerf) {
681                        return V1_2::Capabilities::OperandPerformance{
682                                static_cast<V1_2::OperandType>(opPerf.type), opPerf.info};
683                    });
684     return ret;
685 }
686 
convertToV1_3(const V1_0::Capabilities & capabilities)687 V1_3::Capabilities convertToV1_3(const V1_0::Capabilities& capabilities) {
688     return convertToV1_3(convertToV1_2(capabilities));
689 }
690 
convertToV1_3(const V1_1::Capabilities & capabilities)691 V1_3::Capabilities convertToV1_3(const V1_1::Capabilities& capabilities) {
692     return convertToV1_3(convertToV1_2(capabilities));
693 }
694 
convertToV1_3(const V1_2::Capabilities & capabilities)695 V1_3::Capabilities convertToV1_3(const V1_2::Capabilities& capabilities) {
696     V1_3::Capabilities ret = {
697             .relaxedFloat32toFloat16PerformanceScalar =
698                     capabilities.relaxedFloat32toFloat16PerformanceScalar,
699             .relaxedFloat32toFloat16PerformanceTensor =
700                     capabilities.relaxedFloat32toFloat16PerformanceTensor,
701             .ifPerformance = kNoPerformanceInfo,
702             .whilePerformance = kNoPerformanceInfo,
703     };
704     auto& opPerf = ret.operandPerformance;
705     opPerf.resize(capabilities.operandPerformance.size());
706     std::transform(capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
707                    opPerf.begin(), [](V1_2::Capabilities::OperandPerformance opPerf) {
708                        return V1_3::Capabilities::OperandPerformance{
709                                static_cast<V1_3::OperandType>(opPerf.type), opPerf.info};
710                    });
711     return ret;
712 }
713 
convertToV1_3(const V1_3::Capabilities & capabilities)714 V1_3::Capabilities convertToV1_3(const V1_3::Capabilities& capabilities) {
715     return capabilities;
716 }
717 
uncheckedConvertToV1_0(const V1_1::Operation & operation)718 static V1_0::Operation uncheckedConvertToV1_0(const V1_1::Operation& operation) {
719     return {.type = uncheckedConvertToV1_0(operation.type),
720             .inputs = operation.inputs,
721             .outputs = operation.outputs};
722 }
723 
convertToV1_1(const V1_0::Operation & operation)724 static V1_1::Operation convertToV1_1(const V1_0::Operation& operation) {
725     return {.type = convertToV1_1(operation.type),
726             .inputs = operation.inputs,
727             .outputs = operation.outputs};
728 }
729 
uncheckedConvertToV1_0(const hardware::hidl_vec<V1_1::Operation> & operations)730 static hardware::hidl_vec<V1_0::Operation> uncheckedConvertToV1_0(
731         const hardware::hidl_vec<V1_1::Operation>& operations) {
732     hardware::hidl_vec<V1_0::Operation> result(operations.size());
733     std::transform(
734             operations.begin(), operations.end(), result.begin(),
735             [](const V1_1::Operation& operation) { return uncheckedConvertToV1_0(operation); });
736     return result;
737 }
738 
convertToV1_1(const hardware::hidl_vec<V1_0::Operation> & operations)739 static hardware::hidl_vec<V1_1::Operation> convertToV1_1(
740         const hardware::hidl_vec<V1_0::Operation>& operations) {
741     hardware::hidl_vec<V1_1::Operation> result(operations.size());
742     std::transform(operations.begin(), operations.end(), result.begin(),
743                    [](const V1_0::Operation& operation) { return convertToV1_1(operation); });
744     return result;
745 }
746 
compliantWithV1_0(const V1_3::Operand & operand)747 bool compliantWithV1_0(const V1_3::Operand& operand) {
748     return validOperandType(static_cast<V1_0::OperandType>(operand.type)) &&
749            (nonExtensionOperandTypeIsScalar(static_cast<int>(operand.type)) ||
750             operand.dimensions.size() != 0) &&
751            compliantWithV1_0(operand.lifetime);
752 }
753 
compliantWithV1_2(const V1_3::Operand & operand)754 bool compliantWithV1_2(const V1_3::Operand& operand) {
755     return validOperandType(static_cast<V1_2::OperandType>(operand.type)) &&
756            compliantWithV1_0(operand.lifetime);
757 }
758 
compliantWithV1_3(const V1_3::Operand &)759 bool compliantWithV1_3(const V1_3::Operand& /*operand*/) {
760     return true;
761 }
762 
compliantWithAidl(const V1_3::Operand & operand)763 bool compliantWithAidl(const V1_3::Operand& operand) {
764     if (static_cast<std::underlying_type_t<V1_3::OperandType>>(operand.type) >
765         std::numeric_limits<int32_t>::max()) {
766         return false;
767     }
768     if (operand.location.poolIndex > std::numeric_limits<int32_t>::max()) {
769         return false;
770     }
771     if (operand.extraParams.getDiscriminator() ==
772                 V1_2::Operand::ExtraParams::hidl_discriminator::channelQuant &&
773         operand.extraParams.channelQuant().channelDim > std::numeric_limits<int32_t>::max()) {
774         return false;
775     }
776     for (auto dim : operand.dimensions) {
777         if (dim > std::numeric_limits<int32_t>::max()) {
778             return false;
779         }
780     }
781     return true;
782 }
783 
compliantWith(HalVersion version,const V1_3::Model & model,std::set<uint32_t> * noncompliantOperations)784 static bool compliantWith(HalVersion version, const V1_3::Model& model,
785                           std::set<uint32_t>* noncompliantOperations) {
786     // A boolean vector indicating whether each pool is compliant with the target HAL version.
787     std::vector<bool> isPoolCompliant(model.pools.size(), false);
788     std::transform(
789             model.pools.begin(), model.pools.end(), isPoolCompliant.begin(),
790             [version](const hardware::hidl_memory& pool) { return validatePool(pool, version); });
791 
792     // A boolean vector indicating whether each operand is compliant with the target HAL version.
793     std::vector<bool> isOperandCompliant(model.main.operands.size(), false);
794     std::transform(model.main.operands.begin(), model.main.operands.end(),
795                    isOperandCompliant.begin(),
796                    [&isPoolCompliant, version](const V1_3::Operand& op) {
797                        bool is_operand_compliant = false;
798                        switch (version) {
799                            case HalVersion::UNKNOWN:
800                                is_operand_compliant = false;
801                                break;
802                            case HalVersion::V1_0:
803                                is_operand_compliant = compliantWithV1_0(op);
804                                break;
805                            case HalVersion::V1_1:
806                                // There is no V1_1::Operand -- both V1_0::Model
807                                // and V1_1::Model use V1_0::Operand.
808                                is_operand_compliant = compliantWithV1_0(op);
809                                break;
810                            case HalVersion::V1_2:
811                                is_operand_compliant = compliantWithV1_2(op);
812                                break;
813                            case HalVersion::V1_3:
814                                is_operand_compliant = compliantWithV1_3(op);
815                                break;
816                            case HalVersion::AIDL_UNSTABLE:
817                                is_operand_compliant = compliantWithAidl(op);
818                                break;
819                        }
820                        return is_operand_compliant &&
821                               !(op.lifetime == V1_3::OperandLifeTime::CONSTANT_REFERENCE &&
822                                 !isPoolCompliant[op.location.poolIndex]);
823                    });
824 
825     auto allOperandsCompliant = [&isOperandCompliant](const hardware::hidl_vec<uint32_t>& indices) {
826         return std::all_of(
827                 indices.begin(), indices.end(),
828                 [&isOperandCompliant](const uint32_t ind) { return isOperandCompliant[ind]; });
829     };
830 
831     auto localValidateOperation = [&model, version,
832                                    &allOperandsCompliant](const V1_3::Operation& op) {
833         if (!allOperandsCompliant(op.inputs) || !allOperandsCompliant(op.outputs)) return false;
834         int error = validateOperation(static_cast<int32_t>(op.type), op.inputs.size(),
835                                       op.inputs.size() > 0 ? op.inputs.data() : nullptr,
836                                       op.outputs.size(),
837                                       op.outputs.size() > 0 ? op.outputs.data() : nullptr,
838                                       uncheckedConvert(model.main.operands), version);
839         return error == ANEURALNETWORKS_NO_ERROR;
840     };
841 
842     if (noncompliantOperations) {
843         CHECK(noncompliantOperations->empty());
844         for (uint32_t idx = 0; idx < model.main.operations.size(); ++idx) {
845             if (!localValidateOperation(model.main.operations[idx])) {
846                 noncompliantOperations->insert(idx);
847             }
848         }
849         return noncompliantOperations->empty();
850     } else {
851         return std::all_of(model.main.operations.begin(), model.main.operations.end(),
852                            localValidateOperation);
853     }
854 }
855 
compliantWithV1_0(const V1_0::Model &)856 bool compliantWithV1_0(const V1_0::Model& /*model*/) {
857     return true;
858 }
859 
compliantWithV1_0(const V1_1::Model & model)860 bool compliantWithV1_0(const V1_1::Model& model) {
861     // In addition to new enumeration values being introduced in V1_1::Model, a
862     // new flag was introduced to indicate whether or not float32 data can be
863     // calculated using float16 units. This 'relaxComputationFloat32toFloat16'
864     // flag is not relevant in whether a V1_1::Model is compliant with a
865     // V1_0::Model because all 1.0 drivers require strict calculation by default
866     // in the P NN runtime. Even if fp16 calculations are allowed, they can
867     // still be computed by a strict fp32 driver.
868     auto operands = uncheckedConvert(convertToV1_3(model.operands));
869     return std::all_of(model.operations.begin(), model.operations.end(),
870                        [&operands](const V1_1::Operation& op) {
871                            int error = validateOperation(
872                                    static_cast<int32_t>(op.type), op.inputs.size(),
873                                    op.inputs.size() > 0 ? op.inputs.data() : nullptr,
874                                    op.outputs.size(),
875                                    op.outputs.size() > 0 ? op.outputs.data() : nullptr, operands,
876                                    HalVersion::V1_0);
877                            return error == ANEURALNETWORKS_NO_ERROR;
878                        });
879 }
880 
compliantWithV1_0(const V1_2::Model & model,std::set<uint32_t> * noncompliantOperations)881 bool compliantWithV1_0(const V1_2::Model& model, std::set<uint32_t>* noncompliantOperations) {
882     return compliantWith(HalVersion::V1_0, convertToV1_3(model), noncompliantOperations);
883 }
884 
compliantWithV1_0(const V1_3::Model & model,std::set<uint32_t> * noncompliantOperations)885 bool compliantWithV1_0(const V1_3::Model& model, std::set<uint32_t>* noncompliantOperations) {
886     return compliantWith(HalVersion::V1_0, model, noncompliantOperations);
887 }
888 
compliantWithV1_1(const V1_0::Model &)889 bool compliantWithV1_1(const V1_0::Model&) {
890     return true;
891 }
892 
compliantWithV1_1(const V1_1::Model &)893 bool compliantWithV1_1(const V1_1::Model&) {
894     return true;
895 }
896 
compliantWithV1_1(const V1_2::Model & model,std::set<uint32_t> * noncompliantOperations)897 bool compliantWithV1_1(const V1_2::Model& model, std::set<uint32_t>* noncompliantOperations) {
898     return compliantWith(HalVersion::V1_1, convertToV1_3(model), noncompliantOperations);
899 }
900 
compliantWithV1_1(const V1_3::Model & model,std::set<uint32_t> * noncompliantOperations)901 bool compliantWithV1_1(const V1_3::Model& model, std::set<uint32_t>* noncompliantOperations) {
902     return compliantWith(HalVersion::V1_1, model, noncompliantOperations);
903 }
904 
compliantWithV1_2(const V1_0::Model &)905 bool compliantWithV1_2(const V1_0::Model&) {
906     return true;
907 }
908 
compliantWithV1_2(const V1_1::Model &)909 bool compliantWithV1_2(const V1_1::Model&) {
910     return true;
911 }
912 
compliantWithV1_2(const V1_2::Model &,std::set<uint32_t> *)913 bool compliantWithV1_2(const V1_2::Model&, std::set<uint32_t>* /*noncompliantOperations*/) {
914     return true;
915 }
916 
compliantWithV1_2(const V1_3::Model & model,std::set<uint32_t> * noncompliantOperations)917 bool compliantWithV1_2(const V1_3::Model& model, std::set<uint32_t>* noncompliantOperations) {
918     return compliantWith(HalVersion::V1_2, model, noncompliantOperations);
919 }
920 
uncheckedConvertToV1_0(const V1_2::Operation & operation)921 static V1_0::Operation uncheckedConvertToV1_0(const V1_2::Operation& operation) {
922     return {.type = uncheckedConvertToV1_0(operation.type),
923             .inputs = operation.inputs,
924             .outputs = operation.outputs};
925 }
926 
uncheckedConvertToV1_0(const V1_3::Operation & operation)927 static V1_0::Operation uncheckedConvertToV1_0(const V1_3::Operation& operation) {
928     return {.type = uncheckedConvertToV1_0(operation.type),
929             .inputs = operation.inputs,
930             .outputs = operation.outputs};
931 }
932 
uncheckedConvertToV1_1(const V1_2::Operation & operation)933 static V1_1::Operation uncheckedConvertToV1_1(const V1_2::Operation& operation) {
934     return {.type = uncheckedConvertToV1_1(operation.type),
935             .inputs = operation.inputs,
936             .outputs = operation.outputs};
937 }
938 
uncheckedConvertToV1_1(const V1_3::Operation & operation)939 static V1_1::Operation uncheckedConvertToV1_1(const V1_3::Operation& operation) {
940     return {.type = uncheckedConvertToV1_1(operation.type),
941             .inputs = operation.inputs,
942             .outputs = operation.outputs};
943 }
944 
convertToV1_2(const V1_0::Operation & operation)945 static V1_2::Operation convertToV1_2(const V1_0::Operation& operation) {
946     return {.type = convertToV1_2(operation.type),
947             .inputs = operation.inputs,
948             .outputs = operation.outputs};
949 }
950 
convertToV1_2(const V1_1::Operation & operation)951 static V1_2::Operation convertToV1_2(const V1_1::Operation& operation) {
952     return {.type = convertToV1_2(operation.type),
953             .inputs = operation.inputs,
954             .outputs = operation.outputs};
955 }
956 
uncheckedConvertToV1_2(const V1_3::Operation & operation)957 static V1_2::Operation uncheckedConvertToV1_2(const V1_3::Operation& operation) {
958     return {.type = uncheckedConvertToV1_2(operation.type),
959             .inputs = operation.inputs,
960             .outputs = operation.outputs};
961 }
962 
convertToV1_3(const V1_0::Operation & operation)963 static V1_3::Operation convertToV1_3(const V1_0::Operation& operation) {
964     return {.type = convertToV1_3(operation.type),
965             .inputs = operation.inputs,
966             .outputs = operation.outputs};
967 }
968 
convertToV1_3(const V1_1::Operation & operation)969 static V1_3::Operation convertToV1_3(const V1_1::Operation& operation) {
970     return {.type = convertToV1_3(operation.type),
971             .inputs = operation.inputs,
972             .outputs = operation.outputs};
973 }
974 
convertToV1_3(const V1_2::Operation & operation)975 static V1_3::Operation convertToV1_3(const V1_2::Operation& operation) {
976     return {.type = convertToV1_3(operation.type),
977             .inputs = operation.inputs,
978             .outputs = operation.outputs};
979 }
980 
uncheckedConvertToV1_0(const hardware::hidl_vec<V1_3::Operation> & operations)981 static hardware::hidl_vec<V1_0::Operation> uncheckedConvertToV1_0(
982         const hardware::hidl_vec<V1_3::Operation>& operations) {
983     hardware::hidl_vec<V1_0::Operation> result(operations.size());
984     std::transform(
985             operations.begin(), operations.end(), result.begin(),
986             [](const V1_3::Operation& operation) { return uncheckedConvertToV1_0(operation); });
987     return result;
988 }
989 
uncheckedConvertToV1_0(const hardware::hidl_vec<V1_2::Operation> & operations)990 static hardware::hidl_vec<V1_0::Operation> uncheckedConvertToV1_0(
991         const hardware::hidl_vec<V1_2::Operation>& operations) {
992     hardware::hidl_vec<V1_0::Operation> result(operations.size());
993     std::transform(
994             operations.begin(), operations.end(), result.begin(),
995             [](const V1_2::Operation& operation) { return uncheckedConvertToV1_0(operation); });
996     return result;
997 }
998 
uncheckedConvertToV1_2(const hardware::hidl_vec<V1_3::Operation> & operations)999 static hardware::hidl_vec<V1_2::Operation> uncheckedConvertToV1_2(
1000         const hardware::hidl_vec<V1_3::Operation>& operations) {
1001     hardware::hidl_vec<V1_2::Operation> result(operations.size());
1002     std::transform(
1003             operations.begin(), operations.end(), result.begin(),
1004             [](const V1_3::Operation& operation) { return uncheckedConvertToV1_2(operation); });
1005     return result;
1006 }
1007 
uncheckedConvertToV1_1(const hardware::hidl_vec<V1_2::Operation> & operations)1008 static hardware::hidl_vec<V1_1::Operation> uncheckedConvertToV1_1(
1009         const hardware::hidl_vec<V1_2::Operation>& operations) {
1010     hardware::hidl_vec<V1_1::Operation> result(operations.size());
1011     std::transform(
1012             operations.begin(), operations.end(), result.begin(),
1013             [](const V1_2::Operation& operation) { return uncheckedConvertToV1_1(operation); });
1014     return result;
1015 }
1016 
uncheckedConvertToV1_1(const hardware::hidl_vec<V1_3::Operation> & operations)1017 static hardware::hidl_vec<V1_1::Operation> uncheckedConvertToV1_1(
1018         const hardware::hidl_vec<V1_3::Operation>& operations) {
1019     hardware::hidl_vec<V1_1::Operation> result(operations.size());
1020     std::transform(
1021             operations.begin(), operations.end(), result.begin(),
1022             [](const V1_3::Operation& operation) { return uncheckedConvertToV1_1(operation); });
1023     return result;
1024 }
1025 
convertToV1_2(const hardware::hidl_vec<V1_0::Operation> & operations)1026 static hardware::hidl_vec<V1_2::Operation> convertToV1_2(
1027         const hardware::hidl_vec<V1_0::Operation>& operations) {
1028     hardware::hidl_vec<V1_2::Operation> result(operations.size());
1029     std::transform(operations.begin(), operations.end(), result.begin(),
1030                    [](const V1_0::Operation& operation) { return convertToV1_2(operation); });
1031     return result;
1032 }
1033 
convertToV1_2(const hardware::hidl_vec<V1_1::Operation> & operations)1034 static hardware::hidl_vec<V1_2::Operation> convertToV1_2(
1035         const hardware::hidl_vec<V1_1::Operation>& operations) {
1036     hardware::hidl_vec<V1_2::Operation> result(operations.size());
1037     std::transform(operations.begin(), operations.end(), result.begin(),
1038                    [](const V1_1::Operation& operation) { return convertToV1_2(operation); });
1039     return result;
1040 }
1041 
convertToV1_3(const hardware::hidl_vec<V1_0::Operation> & operations)1042 static hardware::hidl_vec<V1_3::Operation> convertToV1_3(
1043         const hardware::hidl_vec<V1_0::Operation>& operations) {
1044     hardware::hidl_vec<V1_3::Operation> result(operations.size());
1045     std::transform(operations.begin(), operations.end(), result.begin(),
1046                    [](const V1_0::Operation& operation) { return convertToV1_3(operation); });
1047     return result;
1048 }
1049 
convertToV1_3(const hardware::hidl_vec<V1_1::Operation> & operations)1050 static hardware::hidl_vec<V1_3::Operation> convertToV1_3(
1051         const hardware::hidl_vec<V1_1::Operation>& operations) {
1052     hardware::hidl_vec<V1_3::Operation> result(operations.size());
1053     std::transform(operations.begin(), operations.end(), result.begin(),
1054                    [](const V1_1::Operation& operation) { return convertToV1_3(operation); });
1055     return result;
1056 }
1057 
convertToV1_3(const hardware::hidl_vec<V1_2::Operation> & operations)1058 static hardware::hidl_vec<V1_3::Operation> convertToV1_3(
1059         const hardware::hidl_vec<V1_2::Operation>& operations) {
1060     hardware::hidl_vec<V1_3::Operation> result(operations.size());
1061     std::transform(operations.begin(), operations.end(), result.begin(),
1062                    [](const V1_2::Operation& operation) { return convertToV1_3(operation); });
1063     return result;
1064 }
1065 
compliantWithV1_0(const V1_2::OperandType & operandType)1066 static bool compliantWithV1_0(const V1_2::OperandType& operandType) {
1067     return validOperandType(static_cast<V1_0::OperandType>(operandType));
1068 }
1069 
compliantWithV1_0(const V1_3::OperandType & operandType)1070 static bool compliantWithV1_0(const V1_3::OperandType& operandType) {
1071     return validOperandType(static_cast<V1_0::OperandType>(operandType));
1072 }
1073 
compliantWithV1_2(const V1_3::OperandType & operandType)1074 static bool compliantWithV1_2(const V1_3::OperandType& operandType) {
1075     return validOperandType(static_cast<V1_2::OperandType>(operandType));
1076 }
1077 
convertToV1_0(const V1_2::OperandType & operandType)1078 V1_0::OperandType convertToV1_0(const V1_2::OperandType& operandType) {
1079     if (!compliantWithV1_0(operandType)) {
1080         LOG(ERROR) << "Upcasting non-compliant operand type " << toString(operandType)
1081                    << " from V1_2::OperandType to V1_0::OperandType";
1082     }
1083     return static_cast<V1_0::OperandType>(operandType);
1084 }
1085 
convertToV1_2(const V1_0::OperandType & operandType)1086 V1_2::OperandType convertToV1_2(const V1_0::OperandType& operandType) {
1087     return static_cast<V1_2::OperandType>(operandType);
1088 }
1089 
convertToV1_2(const V1_3::OperandType & operandType)1090 V1_2::OperandType convertToV1_2(const V1_3::OperandType& operandType) {
1091     if (!compliantWithV1_2(operandType)) {
1092         LOG(ERROR) << "Upcasting non-compliant operand type " << toString(operandType)
1093                    << " from V1_3::OperandType to V1_2::OperandType";
1094     }
1095     return static_cast<V1_2::OperandType>(operandType);
1096 }
1097 
convertToV1_0(const V1_3::OperandType & operandType)1098 V1_0::OperandType convertToV1_0(const V1_3::OperandType& operandType) {
1099     if (!compliantWithV1_0(operandType)) {
1100         LOG(ERROR) << "Upcasting non-compliant operand type " << toString(operandType)
1101                    << " from V1_3::Operand to V1_0::Operand";
1102     }
1103     return static_cast<V1_0::OperandType>(operandType);
1104 }
1105 
compliantWithV1_0(V1_0::OperandLifeTime)1106 bool compliantWithV1_0(V1_0::OperandLifeTime /*lifetime*/) {
1107     return true;
1108 }
1109 
compliantWithV1_0(V1_3::OperandLifeTime lifetime)1110 bool compliantWithV1_0(V1_3::OperandLifeTime lifetime) {
1111     return lifetime != V1_3::OperandLifeTime::SUBGRAPH;
1112 }
1113 
compliantWithV1_3(V1_0::OperandLifeTime)1114 bool compliantWithV1_3(V1_0::OperandLifeTime /*lifetime*/) {
1115     return true;
1116 }
1117 
compliantWithV1_3(V1_3::OperandLifeTime)1118 bool compliantWithV1_3(V1_3::OperandLifeTime /*lifetime*/) {
1119     return true;
1120 }
1121 
convertToV1_0(V1_0::OperandLifeTime lifetime)1122 V1_0::OperandLifeTime convertToV1_0(V1_0::OperandLifeTime lifetime) {
1123     return lifetime;
1124 }
1125 
convertToV1_0(V1_3::OperandLifeTime lifetime)1126 V1_0::OperandLifeTime convertToV1_0(V1_3::OperandLifeTime lifetime) {
1127     if (!compliantWithV1_0(lifetime)) {
1128         LOG(ERROR) << "Upcasting non-compliant lifetime " << toString(lifetime)
1129                    << " from V1_3 to V1_0";
1130     }
1131     return static_cast<V1_0::OperandLifeTime>(lifetime);
1132 }
1133 
convertToV1_3(V1_0::OperandLifeTime lifetime)1134 V1_3::OperandLifeTime convertToV1_3(V1_0::OperandLifeTime lifetime) {
1135     return static_cast<V1_3::OperandLifeTime>(lifetime);
1136 }
1137 
convertToV1_3(V1_3::OperandLifeTime lifetime)1138 V1_3::OperandLifeTime convertToV1_3(V1_3::OperandLifeTime lifetime) {
1139     return lifetime;
1140 }
1141 
convertToV1_0(const V1_2::Operand & operand)1142 V1_0::Operand convertToV1_0(const V1_2::Operand& operand) {
1143     return {.type = convertToV1_0(operand.type),
1144             .dimensions = operand.dimensions,
1145             .numberOfConsumers = operand.numberOfConsumers,
1146             .scale = operand.scale,
1147             .zeroPoint = operand.zeroPoint,
1148             .lifetime = convertToV1_0(operand.lifetime),
1149             .location = operand.location};
1150 }
1151 
convertToV1_0(const V1_3::Operand & operand)1152 V1_0::Operand convertToV1_0(const V1_3::Operand& operand) {
1153     return {.type = convertToV1_0(operand.type),
1154             .dimensions = operand.dimensions,
1155             .numberOfConsumers = operand.numberOfConsumers,
1156             .scale = operand.scale,
1157             .zeroPoint = operand.zeroPoint,
1158             .lifetime = convertToV1_0(operand.lifetime),
1159             .location = operand.location};
1160 }
1161 
convertToV1_2(const V1_0::Operand & operand)1162 V1_2::Operand convertToV1_2(const V1_0::Operand& operand) {
1163     return {.type = convertToV1_2(operand.type),
1164             .dimensions = operand.dimensions,
1165             .numberOfConsumers = operand.numberOfConsumers,
1166             .scale = operand.scale,
1167             .zeroPoint = operand.zeroPoint,
1168             .lifetime = operand.lifetime,
1169             .location = operand.location};
1170 }
1171 
convertToV1_2(const V1_3::Operand & operand)1172 V1_2::Operand convertToV1_2(const V1_3::Operand& operand) {
1173     return {.type = convertToV1_2(operand.type),
1174             .dimensions = operand.dimensions,
1175             .numberOfConsumers = operand.numberOfConsumers,
1176             .scale = operand.scale,
1177             .zeroPoint = operand.zeroPoint,
1178             .lifetime = static_cast<V1_0::OperandLifeTime>(operand.lifetime),
1179             .location = operand.location,
1180             .extraParams = operand.extraParams};
1181 }
1182 
convertToV1_3(const V1_0::Operand & operand)1183 V1_3::Operand convertToV1_3(const V1_0::Operand& operand) {
1184     return {.type = static_cast<V1_3::OperandType>(operand.type),
1185             .dimensions = operand.dimensions,
1186             .numberOfConsumers = operand.numberOfConsumers,
1187             .scale = operand.scale,
1188             .zeroPoint = operand.zeroPoint,
1189             .lifetime = convertToV1_3(operand.lifetime),
1190             .location = operand.location};
1191 }
1192 
convertToV1_3(const V1_2::Operand & operand)1193 V1_3::Operand convertToV1_3(const V1_2::Operand& operand) {
1194     return {.type = static_cast<V1_3::OperandType>(operand.type),
1195             .dimensions = operand.dimensions,
1196             .numberOfConsumers = operand.numberOfConsumers,
1197             .scale = operand.scale,
1198             .zeroPoint = operand.zeroPoint,
1199             .lifetime = convertToV1_3(operand.lifetime),
1200             .location = operand.location,
1201             .extraParams = operand.extraParams};
1202 }
1203 
convertToV1_3(const V1_3::Operand & operand)1204 V1_3::Operand convertToV1_3(const V1_3::Operand& operand) {
1205     return operand;
1206 }
1207 
convertToV1_0(const hardware::hidl_vec<V1_0::Operand> & operands)1208 hardware::hidl_vec<V1_0::Operand> convertToV1_0(const hardware::hidl_vec<V1_0::Operand>& operands) {
1209     return operands;
1210 }
1211 
convertToV1_0(const hardware::hidl_vec<V1_2::Operand> & operands)1212 hardware::hidl_vec<V1_0::Operand> convertToV1_0(const hardware::hidl_vec<V1_2::Operand>& operands) {
1213     hardware::hidl_vec<V1_0::Operand> result(operands.size());
1214     std::transform(operands.begin(), operands.end(), result.begin(),
1215                    [](const V1_2::Operand& operand) { return convertToV1_0(operand); });
1216     return result;
1217 }
1218 
convertToV1_0(const hardware::hidl_vec<V1_3::Operand> & operands)1219 hardware::hidl_vec<V1_0::Operand> convertToV1_0(const hardware::hidl_vec<V1_3::Operand>& operands) {
1220     hardware::hidl_vec<V1_0::Operand> result(operands.size());
1221     std::transform(operands.begin(), operands.end(), result.begin(),
1222                    [](const V1_3::Operand& operand) { return convertToV1_0(operand); });
1223     return result;
1224 }
1225 
convertToV1_2(const hardware::hidl_vec<V1_0::Operand> & operands)1226 hardware::hidl_vec<V1_2::Operand> convertToV1_2(const hardware::hidl_vec<V1_0::Operand>& operands) {
1227     hardware::hidl_vec<V1_2::Operand> result(operands.size());
1228     std::transform(operands.begin(), operands.end(), result.begin(),
1229                    [](const V1_0::Operand& operand) { return convertToV1_2(operand); });
1230     return result;
1231 }
1232 
convertToV1_2(const hardware::hidl_vec<V1_2::Operand> & operands)1233 hardware::hidl_vec<V1_2::Operand> convertToV1_2(const hardware::hidl_vec<V1_2::Operand>& operands) {
1234     return operands;
1235 }
1236 
convertToV1_2(const hardware::hidl_vec<V1_3::Operand> & operands)1237 hardware::hidl_vec<V1_2::Operand> convertToV1_2(const hardware::hidl_vec<V1_3::Operand>& operands) {
1238     hardware::hidl_vec<V1_2::Operand> result(operands.size());
1239     std::transform(operands.begin(), operands.end(), result.begin(),
1240                    [](const V1_3::Operand& operand) { return convertToV1_2(operand); });
1241     return result;
1242 }
1243 
convertToV1_3(const hardware::hidl_vec<V1_0::Operand> & operands)1244 hardware::hidl_vec<V1_3::Operand> convertToV1_3(const hardware::hidl_vec<V1_0::Operand>& operands) {
1245     hardware::hidl_vec<V1_3::Operand> result(operands.size());
1246     std::transform(operands.begin(), operands.end(), result.begin(),
1247                    [](const V1_0::Operand& operand) { return convertToV1_3(operand); });
1248     return result;
1249 }
1250 
convertToV1_3(const hardware::hidl_vec<V1_2::Operand> & operands)1251 hardware::hidl_vec<V1_3::Operand> convertToV1_3(const hardware::hidl_vec<V1_2::Operand>& operands) {
1252     hardware::hidl_vec<V1_3::Operand> result(operands.size());
1253     std::transform(operands.begin(), operands.end(), result.begin(),
1254                    [](const V1_2::Operand& operand) { return convertToV1_3(operand); });
1255     return result;
1256 }
1257 
convertToV1_3(const hardware::hidl_vec<V1_3::Operand> & operands)1258 hardware::hidl_vec<V1_3::Operand> convertToV1_3(const hardware::hidl_vec<V1_3::Operand>& operands) {
1259     return operands;
1260 }
1261 
convertToV1_0(const V1_0::Model & model)1262 V1_0::Model convertToV1_0(const V1_0::Model& model) {
1263     return model;
1264 }
1265 
convertToV1_0(const V1_1::Model & model)1266 V1_0::Model convertToV1_0(const V1_1::Model& model) {
1267     if (!compliantWithV1_0(model)) {
1268         LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model))
1269                    << " from V1_1::Model to V1_0::Model";
1270     }
1271     return {.operands = model.operands,
1272             .operations = uncheckedConvertToV1_0(model.operations),
1273             .inputIndexes = model.inputIndexes,
1274             .outputIndexes = model.outputIndexes,
1275             .operandValues = model.operandValues,
1276             .pools = model.pools};
1277 }
1278 
convertToV1_0(const V1_2::Model & model)1279 V1_0::Model convertToV1_0(const V1_2::Model& model) {
1280     if (!compliantWithV1_0(model)) {
1281         LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model))
1282                    << " from V1_2::Model to V1_0::Model";
1283     }
1284     return {.operands = convertToV1_0(model.operands),
1285             .operations = uncheckedConvertToV1_0(model.operations),
1286             .inputIndexes = model.inputIndexes,
1287             .outputIndexes = model.outputIndexes,
1288             .operandValues = model.operandValues,
1289             .pools = model.pools};
1290 }
1291 
convertToV1_0(const V1_3::Model & model)1292 V1_0::Model convertToV1_0(const V1_3::Model& model) {
1293     if (!compliantWithV1_0(model)) {
1294         LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model))
1295                    << " from V1_3::Model to V1_0::Model";
1296     }
1297     return {.operands = convertToV1_0(model.main.operands),
1298             .operations = uncheckedConvertToV1_0(model.main.operations),
1299             .inputIndexes = model.main.inputIndexes,
1300             .outputIndexes = model.main.outputIndexes,
1301             .operandValues = model.operandValues,
1302             .pools = model.pools};
1303 }
1304 
convertToV1_1(const V1_0::Model & model)1305 V1_1::Model convertToV1_1(const V1_0::Model& model) {
1306     return {.operands = model.operands,
1307             .operations = convertToV1_1(model.operations),
1308             .inputIndexes = model.inputIndexes,
1309             .outputIndexes = model.outputIndexes,
1310             .operandValues = model.operandValues,
1311             .pools = model.pools,
1312             .relaxComputationFloat32toFloat16 = false};
1313 }
1314 
convertToV1_1(const V1_1::Model & model)1315 V1_1::Model convertToV1_1(const V1_1::Model& model) {
1316     return model;
1317 }
1318 
convertToV1_1(const V1_2::Model & model)1319 V1_1::Model convertToV1_1(const V1_2::Model& model) {
1320     if (!compliantWithV1_1(model)) {
1321         LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model))
1322                    << " from V1_2::Model to V1_1::Model";
1323     }
1324     return {.operands = convertToV1_0(model.operands),  // Operands in 1.1 and 1.0 are identical.
1325             .operations = uncheckedConvertToV1_1(model.operations),
1326             .inputIndexes = model.inputIndexes,
1327             .outputIndexes = model.outputIndexes,
1328             .operandValues = model.operandValues,
1329             .pools = model.pools,
1330             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16};
1331 }
1332 
convertToV1_1(const V1_3::Model & model)1333 V1_1::Model convertToV1_1(const V1_3::Model& model) {
1334     if (!compliantWithV1_1(model)) {
1335         LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model))
1336                    << " from V1_3::Model to V1_1::Model";
1337     }
1338     return {// Operands in 1.1 and 1.0 are identical.
1339             .operands = convertToV1_0(model.main.operands),
1340             .operations = uncheckedConvertToV1_1(model.main.operations),
1341             .inputIndexes = model.main.inputIndexes,
1342             .outputIndexes = model.main.outputIndexes,
1343             .operandValues = model.operandValues,
1344             .pools = model.pools,
1345             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16};
1346 }
1347 
convertToV1_2(const V1_0::Model & model)1348 V1_2::Model convertToV1_2(const V1_0::Model& model) {
1349     return {.operands = convertToV1_2(model.operands),
1350             .operations = convertToV1_2(model.operations),
1351             .inputIndexes = model.inputIndexes,
1352             .outputIndexes = model.outputIndexes,
1353             .operandValues = model.operandValues,
1354             .pools = model.pools,
1355             .relaxComputationFloat32toFloat16 = false};
1356 }
1357 
convertToV1_2(const V1_1::Model & model)1358 V1_2::Model convertToV1_2(const V1_1::Model& model) {
1359     return {.operands = convertToV1_2(model.operands),
1360             .operations = convertToV1_2(model.operations),
1361             .inputIndexes = model.inputIndexes,
1362             .outputIndexes = model.outputIndexes,
1363             .operandValues = model.operandValues,
1364             .pools = model.pools,
1365             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16};
1366 }
1367 
convertToV1_2(const V1_2::Model & model)1368 V1_2::Model convertToV1_2(const V1_2::Model& model) {
1369     return model;
1370 }
1371 
convertToV1_2(const V1_3::Model & model)1372 V1_2::Model convertToV1_2(const V1_3::Model& model) {
1373     if (!compliantWithV1_2(model)) {
1374         LOG(ERROR) << "Upcasting non-compliant model " << SHOW_IF_DEBUG(toString(model))
1375                    << " from V1_3::Model to V1_2::Model";
1376     }
1377     return {.operands = convertToV1_2(model.main.operands),
1378             .operations = uncheckedConvertToV1_2(model.main.operations),
1379             .inputIndexes = model.main.inputIndexes,
1380             .outputIndexes = model.main.outputIndexes,
1381             .operandValues = model.operandValues,
1382             .pools = model.pools,
1383             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
1384             .extensionNameToPrefix = model.extensionNameToPrefix};
1385 }
1386 
convertToV1_3(const V1_0::Model & model)1387 V1_3::Model convertToV1_3(const V1_0::Model& model) {
1388     return {.main = {.operands = convertToV1_3(model.operands),
1389                      .operations = convertToV1_3(model.operations),
1390                      .inputIndexes = model.inputIndexes,
1391                      .outputIndexes = model.outputIndexes},
1392             .operandValues = model.operandValues,
1393             .pools = model.pools,
1394             .relaxComputationFloat32toFloat16 = false};
1395 }
1396 
convertToV1_3(const V1_1::Model & model)1397 V1_3::Model convertToV1_3(const V1_1::Model& model) {
1398     return {.main = {.operands = convertToV1_3(model.operands),
1399                      .operations = convertToV1_3(model.operations),
1400                      .inputIndexes = model.inputIndexes,
1401                      .outputIndexes = model.outputIndexes},
1402             .operandValues = model.operandValues,
1403             .pools = model.pools,
1404             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16};
1405 }
1406 
convertToV1_3(const V1_2::Model & model)1407 V1_3::Model convertToV1_3(const V1_2::Model& model) {
1408     return {.main = {.operands = convertToV1_3(model.operands),
1409                      .operations = convertToV1_3(model.operations),
1410                      .inputIndexes = model.inputIndexes,
1411                      .outputIndexes = model.outputIndexes},
1412             .operandValues = model.operandValues,
1413             .pools = model.pools,
1414             .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
1415             .extensionNameToPrefix = model.extensionNameToPrefix};
1416 }
1417 
convertToV1_3(const V1_3::Model & model)1418 V1_3::Model convertToV1_3(const V1_3::Model& model) {
1419     return model;
1420 }
1421 
compliantWithV1_0(const V1_0::Request &)1422 bool compliantWithV1_0(const V1_0::Request& /*request*/) {
1423     return true;
1424 }
1425 
compliantWithV1_0(const V1_3::Request & request)1426 bool compliantWithV1_0(const V1_3::Request& request) {
1427     return std::all_of(request.pools.begin(), request.pools.end(), [](const auto& pool) {
1428         if (pool.getDiscriminator() != V1_3::Request::MemoryPool::hidl_discriminator::hidlMemory) {
1429             return false;
1430         }
1431         const auto& name = pool.hidlMemory().name();
1432         return name == "ashmem" || name == "mmap_fd";
1433     });
1434 }
1435 
compliantWithV1_2(const V1_3::Request & request)1436 bool compliantWithV1_2(const V1_3::Request& request) {
1437     return std::all_of(request.pools.begin(), request.pools.end(), [](const auto& pool) {
1438         if (pool.getDiscriminator() != V1_3::Request::MemoryPool::hidl_discriminator::hidlMemory) {
1439             return false;
1440         }
1441         const auto& name = pool.hidlMemory().name();
1442         return name == "ashmem" || name == "mmap_fd" || name == "hardware_buffer_blob" ||
1443                name == "hardware_buffer";
1444     });
1445 }
1446 
convertToV1_0(const V1_3::Request::MemoryPool & pool)1447 static hardware::hidl_memory convertToV1_0(const V1_3::Request::MemoryPool& pool) {
1448     switch (pool.getDiscriminator()) {
1449         case V1_3::Request::MemoryPool::hidl_discriminator::hidlMemory:
1450             return pool.hidlMemory();
1451         case V1_3::Request::MemoryPool::hidl_discriminator::token:
1452             return hardware::hidl_memory{};
1453     }
1454 }
1455 
convertToV1_3(const hardware::hidl_memory & pool)1456 static V1_3::Request::MemoryPool convertToV1_3(const hardware::hidl_memory& pool) {
1457     V1_3::Request::MemoryPool ret;
1458     ret.hidlMemory(pool);
1459     return ret;
1460 }
1461 
convertToV1_0(const V1_0::Request & request)1462 V1_0::Request convertToV1_0(const V1_0::Request& request) {
1463     return request;
1464 }
1465 
uncheckedConvertToV1_0(const V1_3::Request & request)1466 static V1_0::Request uncheckedConvertToV1_0(const V1_3::Request& request) {
1467     hardware::hidl_vec<hardware::hidl_memory> pools(request.pools.size());
1468     std::transform(request.pools.begin(), request.pools.end(), pools.begin(),
1469                    [](const auto& pool) { return convertToV1_0(pool); });
1470     return {.inputs = request.inputs, .outputs = request.outputs, .pools = std::move(pools)};
1471 }
1472 
convertToV1_0(const V1_3::Request & request)1473 V1_0::Request convertToV1_0(const V1_3::Request& request) {
1474     if (!compliantWithV1_0(request)) {
1475         LOG(ERROR) << "Upcasting non-compliant request " << SHOW_IF_DEBUG(toString(request))
1476                    << " from V1_3::Request to V1_0::Request of version 1.0";
1477     }
1478     return uncheckedConvertToV1_0(request);
1479 }
1480 
convertToV1_2(const V1_3::Request & request)1481 V1_0::Request convertToV1_2(const V1_3::Request& request) {
1482     if (!compliantWithV1_2(request)) {
1483         LOG(ERROR) << "Upcasting non-compliant request " << SHOW_IF_DEBUG(toString(request))
1484                    << " from V1_3::Request to V1_0::Request of version 1.2";
1485     }
1486     return uncheckedConvertToV1_0(request);
1487 }
1488 
convertToV1_3(const V1_0::Request & request)1489 V1_3::Request convertToV1_3(const V1_0::Request& request) {
1490     hardware::hidl_vec<V1_3::Request::MemoryPool> pools(request.pools.size());
1491     std::transform(request.pools.begin(), request.pools.end(), pools.begin(),
1492                    [](const auto& pool) { return convertToV1_3(pool); });
1493     return {.inputs = request.inputs, .outputs = request.outputs, .pools = std::move(pools)};
1494 }
1495 
convertToV1_3(const V1_3::Request & request)1496 V1_3::Request convertToV1_3(const V1_3::Request& request) {
1497     return request;
1498 }
1499 
uncheckedConvert(V1_0::ErrorStatus status)1500 ErrorStatus uncheckedConvert(V1_0::ErrorStatus status) {
1501     return handleError(convert(status));
1502 }
1503 
uncheckedConvert(V1_3::ErrorStatus status)1504 ErrorStatus uncheckedConvert(V1_3::ErrorStatus status) {
1505     return handleError(convert(status));
1506 }
1507 
uncheckedConvert(V1_3::OperandType operandType)1508 OperandType uncheckedConvert(V1_3::OperandType operandType) {
1509     return handleError(unvalidatedConvert(operandType));
1510 }
1511 
uncheckedConvert(V1_3::OperationType operandType)1512 OperationType uncheckedConvert(V1_3::OperationType operandType) {
1513     return handleError(unvalidatedConvert(operandType));
1514 }
1515 
uncheckedConvert(V1_3::OperandLifeTime lifetime)1516 Operand::LifeTime uncheckedConvert(V1_3::OperandLifeTime lifetime) {
1517     return handleError(unvalidatedConvert(lifetime));
1518 }
1519 
uncheckedConvert(V1_2::MeasureTiming measure)1520 MeasureTiming uncheckedConvert(V1_2::MeasureTiming measure) {
1521     return handleError(convert(measure));
1522 }
1523 
uncheckedConvert(const V1_0::DataLocation & location)1524 DataLocation uncheckedConvert(const V1_0::DataLocation& location) {
1525     return handleError(unvalidatedConvert(location));
1526 }
1527 
uncheckedConvert(const V1_3::Operand & operand)1528 Operand uncheckedConvert(const V1_3::Operand& operand) {
1529     return handleError(unvalidatedConvert(operand));
1530 }
1531 
uncheckedConvert(const V1_2::Operand::ExtraParams & params)1532 Operand::ExtraParams uncheckedConvert(const V1_2::Operand::ExtraParams& params) {
1533     return handleError(unvalidatedConvert(params));
1534 }
1535 
uncheckedConvert(const V1_2::SymmPerChannelQuantParams & params)1536 Operand::SymmPerChannelQuantParams uncheckedConvert(const V1_2::SymmPerChannelQuantParams& params) {
1537     return handleError(unvalidatedConvert(params));
1538 }
1539 
uncheckedConvert(const hardware::hidl_vec<uint8_t> & params)1540 Operand::ExtensionParams uncheckedConvert(const hardware::hidl_vec<uint8_t>& params) {
1541     return params;
1542 }
1543 
uncheckedConvert(const V1_3::Operation & operation)1544 Operation uncheckedConvert(const V1_3::Operation& operation) {
1545     return handleError(unvalidatedConvert(operation));
1546 }
1547 
1548 template <typename CanonicalType, typename HalType>
convertVec(const hardware::hidl_vec<HalType> & items)1549 static std::vector<CanonicalType> convertVec(const hardware::hidl_vec<HalType>& items) {
1550     std::vector<CanonicalType> result;
1551     result.reserve(items.size());
1552     std::transform(items.begin(), items.end(), std::back_inserter(result),
1553                    [](const HalType& item) { return uncheckedConvert(item); });
1554     return result;
1555 }
1556 
uncheckedConvert(const V1_3::Model & model)1557 Model uncheckedConvert(const V1_3::Model& model) {
1558     return handleError(convert(model));
1559 }
1560 
uncheckedConvert(const V1_3::Subgraph & subgraph)1561 Model::Subgraph uncheckedConvert(const V1_3::Subgraph& subgraph) {
1562     return handleError(unvalidatedConvert(subgraph));
1563 }
1564 
uncheckedConvert(const V1_2::Model::ExtensionNameAndPrefix & x)1565 Model::ExtensionNameAndPrefix uncheckedConvert(const V1_2::Model::ExtensionNameAndPrefix& x) {
1566     return handleError(unvalidatedConvert(x));
1567 }
1568 
uncheckedConvert(const V1_3::Request & request)1569 Request uncheckedConvert(const V1_3::Request& request) {
1570     return handleError(convert(request));
1571 }
1572 
uncheckedConvert(const V1_0::RequestArgument & requestArgument)1573 Request::Argument uncheckedConvert(const V1_0::RequestArgument& requestArgument) {
1574     return handleError(unvalidatedConvert(requestArgument));
1575 }
1576 
uncheckedConvert(const V1_3::Request::MemoryPool & memoryPool)1577 Request::MemoryPool uncheckedConvert(const V1_3::Request::MemoryPool& memoryPool) {
1578     return handleError(unvalidatedConvert(memoryPool));
1579 }
1580 
uncheckedConvert(const V1_2::OutputShape & outputShape)1581 OutputShape uncheckedConvert(const V1_2::OutputShape& outputShape) {
1582     return handleError(unvalidatedConvert(outputShape));
1583 }
1584 
uncheckedConvert(const hardware::hidl_vec<V1_2::OutputShape> & outputShapes)1585 std::vector<OutputShape> uncheckedConvert(
1586         const hardware::hidl_vec<V1_2::OutputShape>& outputShapes) {
1587     return convertVec<OutputShape>(outputShapes);
1588 }
1589 
uncheckedConvert(const V1_3::Capabilities & capabilities)1590 Capabilities uncheckedConvert(const V1_3::Capabilities& capabilities) {
1591     return handleError(convert(capabilities));
1592 }
1593 
uncheckedConvert(const V1_3::Capabilities::OperandPerformance & operandPerformance)1594 Capabilities::OperandPerformance uncheckedConvert(
1595         const V1_3::Capabilities::OperandPerformance& operandPerformance) {
1596     return handleError(unvalidatedConvert(operandPerformance));
1597 }
1598 
uncheckedConvert(const V1_0::PerformanceInfo & performanceInfo)1599 Capabilities::PerformanceInfo uncheckedConvert(const V1_0::PerformanceInfo& performanceInfo) {
1600     return handleError(unvalidatedConvert(performanceInfo));
1601 }
1602 
uncheckedConvert(const V1_2::Extension & extension)1603 Extension uncheckedConvert(const V1_2::Extension& extension) {
1604     return handleError(unvalidatedConvert(extension));
1605 }
1606 
uncheckedConvert(const hardware::hidl_vec<V1_2::Extension> & extensions)1607 std::vector<Extension> uncheckedConvert(const hardware::hidl_vec<V1_2::Extension>& extensions) {
1608     return convertVec<Extension>(extensions);
1609 }
1610 
uncheckedConvert(const V1_2::Extension::OperandTypeInformation & info)1611 Extension::OperandTypeInformation uncheckedConvert(
1612         const V1_2::Extension::OperandTypeInformation& info) {
1613     return handleError(unvalidatedConvert(info));
1614 }
1615 
uncheckedConvert(const V1_3::OptionalTimeoutDuration & timeoutDuration)1616 OptionalDuration uncheckedConvert(const V1_3::OptionalTimeoutDuration& timeoutDuration) {
1617     return handleError(convert(timeoutDuration));
1618 }
1619 
uncheckedConvert(const V1_2::Timing & timing)1620 Timing uncheckedConvert(const V1_2::Timing& timing) {
1621     return handleError(convert(timing));
1622 }
1623 
convertToV1_0(ErrorStatus status)1624 V1_0::ErrorStatus convertToV1_0(ErrorStatus status) {
1625     return static_cast<V1_0::ErrorStatus>(static_cast<int>(status));
1626 }
1627 
convertToV1_3(ErrorStatus status)1628 V1_3::ErrorStatus convertToV1_3(ErrorStatus status) {
1629     return handleError(V1_3::utils::convert(status));
1630 }
1631 
convertToV1_3(OperandType operandType)1632 V1_3::OperandType convertToV1_3(OperandType operandType) {
1633     return handleError(V1_3::utils::unvalidatedConvert(operandType));
1634 }
1635 
convertToV1_3(OperationType operandType)1636 V1_3::OperationType convertToV1_3(OperationType operandType) {
1637     return handleError(V1_3::utils::unvalidatedConvert(operandType));
1638 }
1639 
convertToV1_3(Operand::LifeTime lifetime)1640 V1_3::OperandLifeTime convertToV1_3(Operand::LifeTime lifetime) {
1641     return handleError(V1_3::utils::unvalidatedConvert(lifetime));
1642 }
1643 
convertToV1_1(ExecutionPreference preference)1644 V1_1::ExecutionPreference convertToV1_1(ExecutionPreference preference) {
1645     return handleError(V1_1::utils::convert(preference));
1646 }
1647 
convertToV1_3(Priority priority)1648 V1_3::Priority convertToV1_3(Priority priority) {
1649     return handleError(V1_3::utils::convert(priority));
1650 }
1651 
convertToV1_2(MeasureTiming measure)1652 V1_2::MeasureTiming convertToV1_2(MeasureTiming measure) {
1653     return handleError(V1_2::utils::convert(measure));
1654 }
1655 
convertToV1_0(const DataLocation & location)1656 V1_0::DataLocation convertToV1_0(const DataLocation& location) {
1657     return handleError(V1_0::utils::unvalidatedConvert(location));
1658 }
1659 
convertToV1_3(const Operand & operand)1660 V1_3::Operand convertToV1_3(const Operand& operand) {
1661     return handleError(V1_3::utils::unvalidatedConvert(operand));
1662 }
1663 
convertToV1_2(const Operand::ExtraParams & params)1664 V1_2::Operand::ExtraParams convertToV1_2(const Operand::ExtraParams& params) {
1665     return handleError(V1_2::utils::unvalidatedConvert(params));
1666 }
1667 
convertToV1_2(const Operand::SymmPerChannelQuantParams & params)1668 V1_2::SymmPerChannelQuantParams convertToV1_2(const Operand::SymmPerChannelQuantParams& params) {
1669     return handleError(V1_2::utils::unvalidatedConvert(params));
1670 }
1671 
uncheckedConvert(const Operand::ExtensionParams & params)1672 hardware::hidl_vec<uint8_t> uncheckedConvert(const Operand::ExtensionParams& params) {
1673     return params;
1674 }
1675 
convertToV1_3(const Operation & operation)1676 V1_3::Operation convertToV1_3(const Operation& operation) {
1677     return handleError(V1_3::utils::unvalidatedConvert(operation));
1678 }
1679 
1680 template <typename HalType, typename CanonicalType>
convertVecToV1_0(const std::vector<CanonicalType> & items)1681 static hardware::hidl_vec<HalType> convertVecToV1_0(const std::vector<CanonicalType>& items) {
1682     hardware::hidl_vec<HalType> result(items.size());
1683     std::transform(items.begin(), items.end(), result.begin(),
1684                    [](const CanonicalType& item) { return convertToV1_0(item); });
1685     return result;
1686 }
1687 
1688 template <typename HalType, typename CanonicalType>
convertVecToV1_2(const std::vector<CanonicalType> & items)1689 static hardware::hidl_vec<HalType> convertVecToV1_2(const std::vector<CanonicalType>& items) {
1690     hardware::hidl_vec<HalType> result(items.size());
1691     std::transform(items.begin(), items.end(), result.begin(),
1692                    [](const CanonicalType& item) { return convertToV1_2(item); });
1693     return result;
1694 }
1695 
1696 template <typename HalType, typename CanonicalType>
convertVecToV1_3(const std::vector<CanonicalType> & items)1697 static hardware::hidl_vec<HalType> convertVecToV1_3(const std::vector<CanonicalType>& items) {
1698     hardware::hidl_vec<HalType> result(items.size());
1699     std::transform(items.begin(), items.end(), result.begin(),
1700                    [](const CanonicalType& item) { return convertToV1_3(item); });
1701     return result;
1702 }
1703 
convertToV1_2(const OutputShape & outputShape)1704 V1_2::OutputShape convertToV1_2(const OutputShape& outputShape) {
1705     return handleError(V1_2::utils::unvalidatedConvert(outputShape));
1706 }
1707 
convertToV1_2(const std::vector<OutputShape> & outputShapes)1708 hardware::hidl_vec<V1_2::OutputShape> convertToV1_2(const std::vector<OutputShape>& outputShapes) {
1709     return convertVecToV1_2<V1_2::OutputShape>(outputShapes);
1710 }
1711 
convertToV1_3(const Model & model)1712 V1_3::Model convertToV1_3(const Model& model) {
1713     return handleError(V1_3::utils::convert(model));
1714 }
1715 
convertToV1_3(const Model::Subgraph & subgraph)1716 V1_3::Subgraph convertToV1_3(const Model::Subgraph& subgraph) {
1717     return handleError(V1_3::utils::unvalidatedConvert(subgraph));
1718 }
1719 
convertToV1_2(const Model::ExtensionNameAndPrefix & x)1720 V1_2::Model::ExtensionNameAndPrefix convertToV1_2(const Model::ExtensionNameAndPrefix& x) {
1721     return handleError(V1_2::utils::unvalidatedConvert(x));
1722 }
1723 
convertToV1_3(const Request & request)1724 V1_3::Request convertToV1_3(const Request& request) {
1725     return handleError(V1_3::utils::convert(request));
1726 }
1727 
convertToV1_0(const Request::Argument & requestArgument)1728 V1_0::RequestArgument convertToV1_0(const Request::Argument& requestArgument) {
1729     return handleError(V1_0::utils::unvalidatedConvert(requestArgument));
1730 }
1731 
convertToV1_3(const Request::MemoryPool & memoryPool)1732 V1_3::Request::MemoryPool convertToV1_3(const Request::MemoryPool& memoryPool) {
1733     return handleError(V1_3::utils::unvalidatedConvert(memoryPool));
1734 }
1735 
uncheckedConvert(const hardware::hidl_vec<V1_3::Request::MemoryPool> & memoryPools)1736 std::vector<Request::MemoryPool> uncheckedConvert(
1737         const hardware::hidl_vec<V1_3::Request::MemoryPool>& memoryPools) {
1738     return convertVec<Request::MemoryPool>(memoryPools);
1739 }
1740 
convertToV1_3(const OptionalTimePoint & timePoint)1741 V1_3::OptionalTimePoint convertToV1_3(const OptionalTimePoint& timePoint) {
1742     return handleError(V1_3::utils::convert(timePoint));
1743 }
1744 
convertToV1_3(const OptionalDuration & timeoutDuration)1745 V1_3::OptionalTimeoutDuration convertToV1_3(const OptionalDuration& timeoutDuration) {
1746     return handleError(V1_3::utils::convert(timeoutDuration));
1747 }
1748 
convertToV1_2(const Timing & timing)1749 V1_2::Timing convertToV1_2(const Timing& timing) {
1750     return handleError(V1_2::utils::convert(timing));
1751 }
1752 
convertToV1_3(const BufferRole & bufferRole)1753 V1_3::BufferRole convertToV1_3(const BufferRole& bufferRole) {
1754     return handleError(V1_3::utils::unvalidatedConvert(bufferRole));
1755 }
1756 
convertToV1_3(const std::vector<BufferRole> & bufferRoles)1757 hardware::hidl_vec<V1_3::BufferRole> convertToV1_3(const std::vector<BufferRole>& bufferRoles) {
1758     return convertVecToV1_3<V1_3::BufferRole>(bufferRoles);
1759 }
1760 
convertToV1_0(const Model::OperandValues & operandValues)1761 hardware::hidl_vec<uint8_t> convertToV1_0(const Model::OperandValues& operandValues) {
1762     return handleError(V1_0::utils::unvalidatedConvert(operandValues));
1763 }
1764 
convertToV1_0(const SharedMemory & memory)1765 hardware::hidl_memory convertToV1_0(const SharedMemory& memory) {
1766     return handleError(V1_0::utils::unvalidatedConvert(memory));
1767 }
1768 
uncheckedConvert(const hardware::hidl_memory & memory)1769 SharedMemory uncheckedConvert(const hardware::hidl_memory& memory) {
1770     return handleError(convert(memory));
1771 }
1772 
convertToV1_0(const std::vector<SharedMemory> & memories)1773 hardware::hidl_vec<hardware::hidl_memory> convertToV1_0(const std::vector<SharedMemory>& memories) {
1774     return convertVecToV1_0<hardware::hidl_memory>(memories);
1775 }
1776 
uncheckedConvert(const hardware::hidl_vec<hardware::hidl_memory> & memories)1777 std::vector<SharedMemory> uncheckedConvert(
1778         const hardware::hidl_vec<hardware::hidl_memory>& memories) {
1779     return convertVec<SharedMemory>(memories);
1780 }
1781 
uncheckedConvert(const hardware::hidl_vec<V1_3::Subgraph> & subgraphs)1782 std::vector<Model::Subgraph> uncheckedConvert(const hardware::hidl_vec<V1_3::Subgraph>& subgraphs) {
1783     return convertVec<Model::Subgraph>(subgraphs);
1784 }
1785 
uncheckedConvert(const hardware::hidl_vec<V1_3::Operand> & operands)1786 std::vector<Operand> uncheckedConvert(const hardware::hidl_vec<V1_3::Operand>& operands) {
1787     return convertVec<Operand>(operands);
1788 }
1789 
1790 }  // namespace nn
1791 }  // namespace android
1792