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