blob: 949dd0d1ed85f2b616723cdae5ef04a134231bd9 [file] [log] [blame]
Michael Butlerb98aa6d2020-02-22 22:37:59 -08001/*
2 * Copyright (C) 2020 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#include "Conversions.h"
18
19#include <android-base/logging.h>
20#include <android/hardware/neuralnetworks/1.3/types.h>
21#include <nnapi/OperandTypes.h>
22#include <nnapi/OperationTypes.h>
23#include <nnapi/Result.h>
24#include <nnapi/SharedMemory.h>
25#include <nnapi/TypeUtils.h>
26#include <nnapi/Types.h>
Michael Butler6547b2a2020-11-22 19:36:30 -080027#include <nnapi/Validation.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080028#include <nnapi/hal/1.0/Conversions.h>
29#include <nnapi/hal/1.2/Conversions.h>
30#include <nnapi/hal/CommonUtils.h>
Michael Butler4b276a72020-08-06 23:22:35 -070031#include <nnapi/hal/HandleError.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080032
33#include <algorithm>
34#include <chrono>
35#include <functional>
36#include <iterator>
37#include <limits>
38#include <type_traits>
39#include <utility>
40
41namespace {
42
43template <typename Type>
44constexpr std::underlying_type_t<Type> underlyingType(Type value) {
45 return static_cast<std::underlying_type_t<Type>>(value);
46}
47
Michael Butler6547b2a2020-11-22 19:36:30 -080048constexpr auto kVersion = android::nn::Version::ANDROID_R;
49
Michael Butlerb98aa6d2020-02-22 22:37:59 -080050} // namespace
51
52namespace android::nn {
53namespace {
54
55constexpr auto validOperandType(nn::OperandType operandType) {
56 switch (operandType) {
57 case nn::OperandType::FLOAT32:
58 case nn::OperandType::INT32:
59 case nn::OperandType::UINT32:
60 case nn::OperandType::TENSOR_FLOAT32:
61 case nn::OperandType::TENSOR_INT32:
62 case nn::OperandType::TENSOR_QUANT8_ASYMM:
63 case nn::OperandType::BOOL:
64 case nn::OperandType::TENSOR_QUANT16_SYMM:
65 case nn::OperandType::TENSOR_FLOAT16:
66 case nn::OperandType::TENSOR_BOOL8:
67 case nn::OperandType::FLOAT16:
68 case nn::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
69 case nn::OperandType::TENSOR_QUANT16_ASYMM:
70 case nn::OperandType::TENSOR_QUANT8_SYMM:
71 case nn::OperandType::TENSOR_QUANT8_ASYMM_SIGNED:
72 case nn::OperandType::SUBGRAPH:
73 case nn::OperandType::OEM:
74 case nn::OperandType::TENSOR_OEM_BYTE:
75 return true;
76 }
77 return nn::isExtension(operandType);
78}
79
80using hardware::hidl_vec;
81
82template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -080083using unvalidatedConvertOutput =
84 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080085
86template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -080087GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
88 const hidl_vec<Type>& arguments) {
89 std::vector<unvalidatedConvertOutput<Type>> canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080090 canonical.reserve(arguments.size());
91 for (const auto& argument : arguments) {
Michael Butler6547b2a2020-11-22 19:36:30 -080092 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -080093 }
94 return canonical;
95}
96
97template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -080098GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
99 const hidl_vec<Type>& arguments) {
100 return unvalidatedConvertVec(arguments);
101}
102
103template <typename Type>
104decltype(nn::unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& halObject) {
105 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
106 const auto maybeVersion = validate(canonical);
107 if (!maybeVersion.has_value()) {
108 return error() << maybeVersion.error();
109 }
110 const auto version = maybeVersion.value();
111 if (version > kVersion) {
112 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
113 }
114 return canonical;
115}
116
117template <typename Type>
118GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> validatedConvert(
119 const hidl_vec<Type>& arguments) {
120 std::vector<unvalidatedConvertOutput<Type>> canonical;
121 canonical.reserve(arguments.size());
122 for (const auto& argument : arguments) {
123 canonical.push_back(NN_TRY(validatedConvert(argument)));
124 }
125 return canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800126}
127
128} // anonymous namespace
129
Michael Butler6547b2a2020-11-22 19:36:30 -0800130GeneralResult<OperandType> unvalidatedConvert(const hal::V1_3::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800131 return static_cast<OperandType>(operandType);
132}
133
Michael Butler6547b2a2020-11-22 19:36:30 -0800134GeneralResult<OperationType> unvalidatedConvert(const hal::V1_3::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800135 return static_cast<OperationType>(operationType);
136}
137
Michael Butler6547b2a2020-11-22 19:36:30 -0800138GeneralResult<Priority> unvalidatedConvert(const hal::V1_3::Priority& priority) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800139 return static_cast<Priority>(priority);
140}
141
Michael Butler6547b2a2020-11-22 19:36:30 -0800142GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_3::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800143 const bool validOperandTypes = std::all_of(
144 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
145 [](const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800146 const auto maybeType = unvalidatedConvert(operandPerformance.type);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800147 return !maybeType.has_value() ? false : validOperandType(maybeType.value());
148 });
149 if (!validOperandTypes) {
Michael Butler4b276a72020-08-06 23:22:35 -0700150 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butler6547b2a2020-11-22 19:36:30 -0800151 << "Invalid OperandType when unvalidatedConverting OperandPerformance in "
152 "Capabilities";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800153 }
154
Michael Butler6547b2a2020-11-22 19:36:30 -0800155 auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
Michael Butler4b276a72020-08-06 23:22:35 -0700156 auto table = NN_TRY(hal::utils::makeGeneralFailure(
157 Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
158 nn::ErrorStatus::GENERAL_FAILURE));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800159
160 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800161 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
162 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
163 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
164 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800165 .operandPerformance = std::move(table),
Michael Butler6547b2a2020-11-22 19:36:30 -0800166 .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
167 .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800168 };
169}
170
Michael Butler6547b2a2020-11-22 19:36:30 -0800171GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800172 const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) {
173 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800174 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
175 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800176 };
177}
178
Michael Butler6547b2a2020-11-22 19:36:30 -0800179GeneralResult<Operation> unvalidatedConvert(const hal::V1_3::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800180 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800181 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800182 .inputs = operation.inputs,
183 .outputs = operation.outputs,
184 };
185}
186
Michael Butler6547b2a2020-11-22 19:36:30 -0800187GeneralResult<Operand::LifeTime> unvalidatedConvert(
188 const hal::V1_3::OperandLifeTime& operandLifeTime) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800189 return static_cast<Operand::LifeTime>(operandLifeTime);
190}
191
Michael Butler6547b2a2020-11-22 19:36:30 -0800192GeneralResult<Operand> unvalidatedConvert(const hal::V1_3::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800193 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800194 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800195 .dimensions = operand.dimensions,
196 .scale = operand.scale,
197 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800198 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
199 .location = NN_TRY(unvalidatedConvert(operand.location)),
200 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800201 };
202}
203
Michael Butler6547b2a2020-11-22 19:36:30 -0800204GeneralResult<Model> unvalidatedConvert(const hal::V1_3::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800205 return Model{
Michael Butler6547b2a2020-11-22 19:36:30 -0800206 .main = NN_TRY(unvalidatedConvert(model.main)),
207 .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
208 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
209 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800210 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800211 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800212 };
213}
214
Michael Butler6547b2a2020-11-22 19:36:30 -0800215GeneralResult<Model::Subgraph> unvalidatedConvert(const hal::V1_3::Subgraph& subgraph) {
216 auto operations = NN_TRY(unvalidatedConvert(subgraph.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800217
218 // Verify number of consumers.
219 const auto numberOfConsumers =
220 hal::utils::countNumberOfConsumers(subgraph.operands.size(), operations);
221 CHECK(subgraph.operands.size() == numberOfConsumers.size());
222 for (size_t i = 0; i < subgraph.operands.size(); ++i) {
223 if (subgraph.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler4b276a72020-08-06 23:22:35 -0700224 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
225 << "Invalid numberOfConsumers for operand " << i << ", expected "
226 << numberOfConsumers[i] << " but found "
227 << subgraph.operands[i].numberOfConsumers;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800228 }
229 }
230
231 return Model::Subgraph{
Michael Butler6547b2a2020-11-22 19:36:30 -0800232 .operands = NN_TRY(unvalidatedConvert(subgraph.operands)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800233 .operations = std::move(operations),
234 .inputIndexes = subgraph.inputIndexes,
235 .outputIndexes = subgraph.outputIndexes,
236 };
237}
238
Michael Butler6547b2a2020-11-22 19:36:30 -0800239GeneralResult<BufferDesc> unvalidatedConvert(const hal::V1_3::BufferDesc& bufferDesc) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800240 return BufferDesc{.dimensions = bufferDesc.dimensions};
241}
242
Michael Butler6547b2a2020-11-22 19:36:30 -0800243GeneralResult<BufferRole> unvalidatedConvert(const hal::V1_3::BufferRole& bufferRole) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800244 return BufferRole{
245 .modelIndex = bufferRole.modelIndex,
246 .ioIndex = bufferRole.ioIndex,
247 .frequency = bufferRole.frequency,
248 };
249}
250
Michael Butler6547b2a2020-11-22 19:36:30 -0800251GeneralResult<Request> unvalidatedConvert(const hal::V1_3::Request& request) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800252 return Request{
Michael Butler6547b2a2020-11-22 19:36:30 -0800253 .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
254 .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
255 .pools = NN_TRY(unvalidatedConvert(request.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800256 };
257}
258
Michael Butler6547b2a2020-11-22 19:36:30 -0800259GeneralResult<Request::MemoryPool> unvalidatedConvert(
260 const hal::V1_3::Request::MemoryPool& memoryPool) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800261 using Discriminator = hal::V1_3::Request::MemoryPool::hidl_discriminator;
262 switch (memoryPool.getDiscriminator()) {
263 case Discriminator::hidlMemory:
264 return createSharedMemoryFromHidlMemory(memoryPool.hidlMemory());
265 case Discriminator::token:
266 return static_cast<Request::MemoryDomainToken>(memoryPool.token());
267 }
Michael Butler4b276a72020-08-06 23:22:35 -0700268 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
269 << "Invalid Request::MemoryPool discriminator "
270 << underlyingType(memoryPool.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800271}
272
Michael Butler6547b2a2020-11-22 19:36:30 -0800273GeneralResult<OptionalTimePoint> unvalidatedConvert(
274 const hal::V1_3::OptionalTimePoint& optionalTimePoint) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800275 constexpr auto kTimePointMaxCount = TimePoint::max().time_since_epoch().count();
Michael Butler4b276a72020-08-06 23:22:35 -0700276 const auto makeTimePoint = [](uint64_t count) -> GeneralResult<OptionalTimePoint> {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800277 if (count > kTimePointMaxCount) {
Michael Butler4b276a72020-08-06 23:22:35 -0700278 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butler6547b2a2020-11-22 19:36:30 -0800279 << "Unable to unvalidatedConvert OptionalTimePoint because the count exceeds "
280 "the max";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800281 }
282 const auto nanoseconds = std::chrono::nanoseconds{count};
283 return TimePoint{nanoseconds};
284 };
285
286 using Discriminator = hal::V1_3::OptionalTimePoint::hidl_discriminator;
287 switch (optionalTimePoint.getDiscriminator()) {
288 case Discriminator::none:
289 return std::nullopt;
290 case Discriminator::nanosecondsSinceEpoch:
291 return makeTimePoint(optionalTimePoint.nanosecondsSinceEpoch());
292 }
Michael Butler4b276a72020-08-06 23:22:35 -0700293 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
294 << "Invalid OptionalTimePoint discriminator "
295 << underlyingType(optionalTimePoint.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800296}
297
Michael Butler6547b2a2020-11-22 19:36:30 -0800298GeneralResult<OptionalTimeoutDuration> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800299 const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration) {
300 constexpr auto kTimeoutDurationMaxCount = TimeoutDuration::max().count();
Michael Butler4b276a72020-08-06 23:22:35 -0700301 const auto makeTimeoutDuration = [](uint64_t count) -> GeneralResult<OptionalTimeoutDuration> {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800302 if (count > kTimeoutDurationMaxCount) {
Michael Butler4b276a72020-08-06 23:22:35 -0700303 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butler6547b2a2020-11-22 19:36:30 -0800304 << "Unable to unvalidatedConvert OptionalTimeoutDuration because the count "
305 "exceeds the max";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800306 }
307 return TimeoutDuration{count};
308 };
309
310 using Discriminator = hal::V1_3::OptionalTimeoutDuration::hidl_discriminator;
311 switch (optionalTimeoutDuration.getDiscriminator()) {
312 case Discriminator::none:
313 return std::nullopt;
314 case Discriminator::nanoseconds:
315 return makeTimeoutDuration(optionalTimeoutDuration.nanoseconds());
316 }
Michael Butler4b276a72020-08-06 23:22:35 -0700317 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
318 << "Invalid OptionalTimeoutDuration discriminator "
319 << underlyingType(optionalTimeoutDuration.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800320}
321
Michael Butler6547b2a2020-11-22 19:36:30 -0800322GeneralResult<ErrorStatus> unvalidatedConvert(const hal::V1_3::ErrorStatus& status) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800323 switch (status) {
324 case hal::V1_3::ErrorStatus::NONE:
325 case hal::V1_3::ErrorStatus::DEVICE_UNAVAILABLE:
326 case hal::V1_3::ErrorStatus::GENERAL_FAILURE:
327 case hal::V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
328 case hal::V1_3::ErrorStatus::INVALID_ARGUMENT:
329 case hal::V1_3::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
330 case hal::V1_3::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
331 case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
332 case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
333 return static_cast<ErrorStatus>(status);
334 }
Michael Butler4b276a72020-08-06 23:22:35 -0700335 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
336 << "Invalid ErrorStatus " << underlyingType(status);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800337}
338
Michael Butler6547b2a2020-11-22 19:36:30 -0800339GeneralResult<Priority> convert(const hal::V1_3::Priority& priority) {
340 return validatedConvert(priority);
341}
342
343GeneralResult<Capabilities> convert(const hal::V1_3::Capabilities& capabilities) {
344 return validatedConvert(capabilities);
345}
346
347GeneralResult<Model> convert(const hal::V1_3::Model& model) {
348 return validatedConvert(model);
349}
350
351GeneralResult<BufferDesc> convert(const hal::V1_3::BufferDesc& bufferDesc) {
352 return validatedConvert(bufferDesc);
353}
354
355GeneralResult<Request> convert(const hal::V1_3::Request& request) {
356 return validatedConvert(request);
357}
358
359GeneralResult<OptionalTimePoint> convert(const hal::V1_3::OptionalTimePoint& optionalTimePoint) {
360 return validatedConvert(optionalTimePoint);
361}
362
363GeneralResult<OptionalTimeoutDuration> convert(
364 const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration) {
365 return validatedConvert(optionalTimeoutDuration);
366}
367
368GeneralResult<ErrorStatus> convert(const hal::V1_3::ErrorStatus& errorStatus) {
369 return validatedConvert(errorStatus);
370}
371
372GeneralResult<SharedHandle> convert(const hardware::hidl_handle& handle) {
373 return validatedConvert(handle);
374}
375
376GeneralResult<Memory> convert(const hardware::hidl_memory& memory) {
377 return validatedConvert(memory);
378}
379
Michael Butler4b276a72020-08-06 23:22:35 -0700380GeneralResult<std::vector<BufferRole>> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800381 const hardware::hidl_vec<hal::V1_3::BufferRole>& bufferRoles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800382 return validatedConvert(bufferRoles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800383}
384
385} // namespace android::nn
386
387namespace android::hardware::neuralnetworks::V1_3::utils {
388namespace {
389
Michael Butler6547b2a2020-11-22 19:36:30 -0800390using utils::unvalidatedConvert;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800391
Michael Butler6547b2a2020-11-22 19:36:30 -0800392nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800393 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800394 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800395}
396
Michael Butler6547b2a2020-11-22 19:36:30 -0800397nn::GeneralResult<V1_0::DataLocation> unvalidatedConvert(const nn::DataLocation& dataLocation) {
398 return V1_0::utils::unvalidatedConvert(dataLocation);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800399}
400
Michael Butler6547b2a2020-11-22 19:36:30 -0800401nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
402 const nn::Model::OperandValues& operandValues) {
403 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800404}
405
Michael Butler6547b2a2020-11-22 19:36:30 -0800406nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
407 return V1_2::utils::unvalidatedConvert(handle);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800408}
409
Michael Butler6547b2a2020-11-22 19:36:30 -0800410nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory) {
411 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800412}
413
Michael Butler6547b2a2020-11-22 19:36:30 -0800414nn::GeneralResult<V1_0::RequestArgument> unvalidatedConvert(const nn::Request::Argument& argument) {
415 return V1_0::utils::unvalidatedConvert(argument);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800416}
417
Michael Butler6547b2a2020-11-22 19:36:30 -0800418nn::GeneralResult<V1_2::Operand::ExtraParams> unvalidatedConvert(
419 const nn::Operand::ExtraParams& extraParams) {
420 return V1_2::utils::unvalidatedConvert(extraParams);
421}
422
423nn::GeneralResult<V1_2::Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800424 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800425 return V1_2::utils::unvalidatedConvert(extensionNameAndPrefix);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800426}
427
428template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -0800429using unvalidatedConvertOutput =
430 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800431
432template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800433nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
434 const std::vector<Type>& arguments) {
435 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800436 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800437 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800438 }
439 return halObject;
440}
441
442template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800443nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
444 const std::vector<Type>& arguments) {
445 return unvalidatedConvertVec(arguments);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800446}
447
Michael Butler4b276a72020-08-06 23:22:35 -0700448nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Memory& memory) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800449 Request::MemoryPool ret;
Michael Butler6547b2a2020-11-22 19:36:30 -0800450 ret.hidlMemory(NN_TRY(unvalidatedConvert(memory)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800451 return ret;
452}
453
Michael Butler4b276a72020-08-06 23:22:35 -0700454nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Request::MemoryDomainToken& token) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800455 Request::MemoryPool ret;
456 ret.token(underlyingType(token));
457 return ret;
458}
459
Michael Butler4b276a72020-08-06 23:22:35 -0700460nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::SharedBuffer& /*buffer*/) {
461 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Unable to make memory pool from IBuffer";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800462}
463
Michael Butler6547b2a2020-11-22 19:36:30 -0800464using utils::unvalidatedConvert;
465
466template <typename Type>
467decltype(unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& canonical) {
468 const auto maybeVersion = nn::validate(canonical);
469 if (!maybeVersion.has_value()) {
470 return nn::error() << maybeVersion.error();
471 }
472 const auto version = maybeVersion.value();
473 if (version > kVersion) {
474 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
475 }
476 return unvalidatedConvert(canonical);
477}
478
479template <typename Type>
480nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> validatedConvert(
481 const std::vector<Type>& arguments) {
482 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
483 for (size_t i = 0; i < arguments.size(); ++i) {
484 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
485 }
486 return halObject;
487}
488
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800489} // anonymous namespace
490
Michael Butler6547b2a2020-11-22 19:36:30 -0800491nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800492 return static_cast<OperandType>(operandType);
493}
494
Michael Butler6547b2a2020-11-22 19:36:30 -0800495nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800496 return static_cast<OperationType>(operationType);
497}
498
Michael Butler6547b2a2020-11-22 19:36:30 -0800499nn::GeneralResult<Priority> unvalidatedConvert(const nn::Priority& priority) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800500 return static_cast<Priority>(priority);
501}
502
Michael Butler6547b2a2020-11-22 19:36:30 -0800503nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800504 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
505 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
506 std::copy_if(capabilities.operandPerformance.asVector().begin(),
507 capabilities.operandPerformance.asVector().end(),
508 std::back_inserter(operandPerformance),
509 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
510 return nn::validOperandType(operandPerformance.type);
511 });
512
513 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800514 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
515 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
516 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
517 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
518 .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
519 .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
520 .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800521 };
522}
523
Michael Butler6547b2a2020-11-22 19:36:30 -0800524nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800525 const nn::Capabilities::OperandPerformance& operandPerformance) {
526 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800527 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
528 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800529 };
530}
531
Michael Butler6547b2a2020-11-22 19:36:30 -0800532nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800533 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800534 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800535 .inputs = operation.inputs,
536 .outputs = operation.outputs,
537 };
538}
539
Michael Butler6547b2a2020-11-22 19:36:30 -0800540nn::GeneralResult<OperandLifeTime> unvalidatedConvert(
541 const nn::Operand::LifeTime& operandLifeTime) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800542 if (operandLifeTime == nn::Operand::LifeTime::POINTER) {
Michael Butler4b276a72020-08-06 23:22:35 -0700543 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800544 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800545 }
546 return static_cast<OperandLifeTime>(operandLifeTime);
547}
548
Michael Butler6547b2a2020-11-22 19:36:30 -0800549nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800550 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800551 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800552 .dimensions = operand.dimensions,
553 .numberOfConsumers = 0,
554 .scale = operand.scale,
555 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800556 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
557 .location = NN_TRY(unvalidatedConvert(operand.location)),
558 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800559 };
560}
561
Michael Butler6547b2a2020-11-22 19:36:30 -0800562nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800563 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700564 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800565 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800566 }
567
568 return Model{
Michael Butler6547b2a2020-11-22 19:36:30 -0800569 .main = NN_TRY(unvalidatedConvert(model.main)),
570 .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
571 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
572 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800573 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800574 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800575 };
576}
577
Michael Butler6547b2a2020-11-22 19:36:30 -0800578nn::GeneralResult<Subgraph> unvalidatedConvert(const nn::Model::Subgraph& subgraph) {
579 auto operands = NN_TRY(unvalidatedConvert(subgraph.operands));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800580
581 // Update number of consumers.
582 const auto numberOfConsumers =
583 hal::utils::countNumberOfConsumers(operands.size(), subgraph.operations);
584 CHECK(operands.size() == numberOfConsumers.size());
585 for (size_t i = 0; i < operands.size(); ++i) {
586 operands[i].numberOfConsumers = numberOfConsumers[i];
587 }
588
589 return Subgraph{
590 .operands = std::move(operands),
Michael Butler6547b2a2020-11-22 19:36:30 -0800591 .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800592 .inputIndexes = subgraph.inputIndexes,
593 .outputIndexes = subgraph.outputIndexes,
594 };
595}
596
Michael Butler6547b2a2020-11-22 19:36:30 -0800597nn::GeneralResult<BufferDesc> unvalidatedConvert(const nn::BufferDesc& bufferDesc) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800598 return BufferDesc{.dimensions = bufferDesc.dimensions};
599}
600
Michael Butler6547b2a2020-11-22 19:36:30 -0800601nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRole) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800602 return BufferRole{
603 .modelIndex = bufferRole.modelIndex,
604 .ioIndex = bufferRole.ioIndex,
605 .frequency = bufferRole.frequency,
606 };
607}
608
Michael Butler6547b2a2020-11-22 19:36:30 -0800609nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800610 if (!hal::utils::hasNoPointerData(request)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700611 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800612 << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800613 }
614
615 return Request{
Michael Butler6547b2a2020-11-22 19:36:30 -0800616 .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
617 .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
618 .pools = NN_TRY(unvalidatedConvert(request.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800619 };
620}
621
Michael Butler6547b2a2020-11-22 19:36:30 -0800622nn::GeneralResult<Request::MemoryPool> unvalidatedConvert(
623 const nn::Request::MemoryPool& memoryPool) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800624 return std::visit([](const auto& o) { return makeMemoryPool(o); }, memoryPool);
625}
626
Michael Butler6547b2a2020-11-22 19:36:30 -0800627nn::GeneralResult<OptionalTimePoint> unvalidatedConvert(
628 const nn::OptionalTimePoint& optionalTimePoint) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800629 OptionalTimePoint ret;
630 if (optionalTimePoint.has_value()) {
631 const auto count = optionalTimePoint.value().time_since_epoch().count();
632 if (count < 0) {
Michael Butler4b276a72020-08-06 23:22:35 -0700633 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butler6547b2a2020-11-22 19:36:30 -0800634 << "Unable to unvalidatedConvert OptionalTimePoint because time since epoch "
635 "count is "
Michael Butler4b276a72020-08-06 23:22:35 -0700636 "negative";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800637 }
638 ret.nanosecondsSinceEpoch(count);
639 }
640 return ret;
641}
642
Michael Butler6547b2a2020-11-22 19:36:30 -0800643nn::GeneralResult<OptionalTimeoutDuration> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800644 const nn::OptionalTimeoutDuration& optionalTimeoutDuration) {
645 OptionalTimeoutDuration ret;
646 if (optionalTimeoutDuration.has_value()) {
647 const auto count = optionalTimeoutDuration.value().count();
648 if (count < 0) {
Michael Butler4b276a72020-08-06 23:22:35 -0700649 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butler6547b2a2020-11-22 19:36:30 -0800650 << "Unable to unvalidatedConvert OptionalTimeoutDuration because count is "
651 "negative";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800652 }
653 ret.nanoseconds(count);
654 }
655 return ret;
656}
657
Michael Butler6547b2a2020-11-22 19:36:30 -0800658nn::GeneralResult<ErrorStatus> unvalidatedConvert(const nn::ErrorStatus& errorStatus) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800659 switch (errorStatus) {
660 case nn::ErrorStatus::NONE:
661 case nn::ErrorStatus::DEVICE_UNAVAILABLE:
662 case nn::ErrorStatus::GENERAL_FAILURE:
663 case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
664 case nn::ErrorStatus::INVALID_ARGUMENT:
665 case nn::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
666 case nn::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
667 case nn::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
668 case nn::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
669 return static_cast<ErrorStatus>(errorStatus);
670 default:
671 return ErrorStatus::GENERAL_FAILURE;
672 }
673}
674
Michael Butler6547b2a2020-11-22 19:36:30 -0800675nn::GeneralResult<Priority> convert(const nn::Priority& priority) {
676 return validatedConvert(priority);
677}
678
679nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
680 return validatedConvert(capabilities);
681}
682
683nn::GeneralResult<Model> convert(const nn::Model& model) {
684 return validatedConvert(model);
685}
686
687nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc) {
688 return validatedConvert(bufferDesc);
689}
690
691nn::GeneralResult<Request> convert(const nn::Request& request) {
692 return validatedConvert(request);
693}
694
695nn::GeneralResult<OptionalTimePoint> convert(const nn::OptionalTimePoint& optionalTimePoint) {
696 return validatedConvert(optionalTimePoint);
697}
698
699nn::GeneralResult<OptionalTimeoutDuration> convert(
700 const nn::OptionalTimeoutDuration& optionalTimeoutDuration) {
701 return validatedConvert(optionalTimeoutDuration);
702}
703
704nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus) {
705 return validatedConvert(errorStatus);
706}
707
708nn::GeneralResult<hidl_handle> convert(const nn::SharedHandle& handle) {
709 return validatedConvert(handle);
710}
711
712nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory) {
713 return validatedConvert(memory);
714}
715
Michael Butler4b276a72020-08-06 23:22:35 -0700716nn::GeneralResult<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800717 return validatedConvert(bufferRoles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800718}
719
720} // namespace android::hardware::neuralnetworks::V1_3::utils