blob: 8b7db2b90e49e7e9b3b392eb3821d245039e8e7a [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 using Discriminator = hal::V1_3::OptionalTimePoint::hidl_discriminator;
276 switch (optionalTimePoint.getDiscriminator()) {
277 case Discriminator::none:
Michael Butler4024d8f2020-12-04 17:38:20 -0800278 return {};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800279 case Discriminator::nanosecondsSinceEpoch:
Michael Butler4024d8f2020-12-04 17:38:20 -0800280 return TimePoint{Duration{optionalTimePoint.nanosecondsSinceEpoch()}};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800281 }
Michael Butler4b276a72020-08-06 23:22:35 -0700282 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
283 << "Invalid OptionalTimePoint discriminator "
284 << underlyingType(optionalTimePoint.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800285}
286
Michael Butler4024d8f2020-12-04 17:38:20 -0800287GeneralResult<OptionalDuration> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800288 const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800289 using Discriminator = hal::V1_3::OptionalTimeoutDuration::hidl_discriminator;
290 switch (optionalTimeoutDuration.getDiscriminator()) {
291 case Discriminator::none:
Michael Butler4024d8f2020-12-04 17:38:20 -0800292 return {};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800293 case Discriminator::nanoseconds:
Michael Butler4024d8f2020-12-04 17:38:20 -0800294 return Duration(optionalTimeoutDuration.nanoseconds());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800295 }
Michael Butler4b276a72020-08-06 23:22:35 -0700296 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
297 << "Invalid OptionalTimeoutDuration discriminator "
298 << underlyingType(optionalTimeoutDuration.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800299}
300
Michael Butler6547b2a2020-11-22 19:36:30 -0800301GeneralResult<ErrorStatus> unvalidatedConvert(const hal::V1_3::ErrorStatus& status) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800302 switch (status) {
303 case hal::V1_3::ErrorStatus::NONE:
304 case hal::V1_3::ErrorStatus::DEVICE_UNAVAILABLE:
305 case hal::V1_3::ErrorStatus::GENERAL_FAILURE:
306 case hal::V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
307 case hal::V1_3::ErrorStatus::INVALID_ARGUMENT:
308 case hal::V1_3::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
309 case hal::V1_3::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
310 case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
311 case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
312 return static_cast<ErrorStatus>(status);
313 }
Michael Butler4b276a72020-08-06 23:22:35 -0700314 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
315 << "Invalid ErrorStatus " << underlyingType(status);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800316}
317
Michael Butler6547b2a2020-11-22 19:36:30 -0800318GeneralResult<Priority> convert(const hal::V1_3::Priority& priority) {
319 return validatedConvert(priority);
320}
321
322GeneralResult<Capabilities> convert(const hal::V1_3::Capabilities& capabilities) {
323 return validatedConvert(capabilities);
324}
325
326GeneralResult<Model> convert(const hal::V1_3::Model& model) {
327 return validatedConvert(model);
328}
329
330GeneralResult<BufferDesc> convert(const hal::V1_3::BufferDesc& bufferDesc) {
331 return validatedConvert(bufferDesc);
332}
333
334GeneralResult<Request> convert(const hal::V1_3::Request& request) {
335 return validatedConvert(request);
336}
337
338GeneralResult<OptionalTimePoint> convert(const hal::V1_3::OptionalTimePoint& optionalTimePoint) {
339 return validatedConvert(optionalTimePoint);
340}
341
Michael Butler4024d8f2020-12-04 17:38:20 -0800342GeneralResult<OptionalDuration> convert(
Michael Butler6547b2a2020-11-22 19:36:30 -0800343 const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration) {
344 return validatedConvert(optionalTimeoutDuration);
345}
346
347GeneralResult<ErrorStatus> convert(const hal::V1_3::ErrorStatus& errorStatus) {
348 return validatedConvert(errorStatus);
349}
350
351GeneralResult<SharedHandle> convert(const hardware::hidl_handle& handle) {
352 return validatedConvert(handle);
353}
354
355GeneralResult<Memory> convert(const hardware::hidl_memory& memory) {
356 return validatedConvert(memory);
357}
358
Michael Butler4b276a72020-08-06 23:22:35 -0700359GeneralResult<std::vector<BufferRole>> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800360 const hardware::hidl_vec<hal::V1_3::BufferRole>& bufferRoles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800361 return validatedConvert(bufferRoles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800362}
363
364} // namespace android::nn
365
366namespace android::hardware::neuralnetworks::V1_3::utils {
367namespace {
368
Michael Butler6547b2a2020-11-22 19:36:30 -0800369using utils::unvalidatedConvert;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800370
Michael Butler6547b2a2020-11-22 19:36:30 -0800371nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800372 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800373 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800374}
375
Michael Butler6547b2a2020-11-22 19:36:30 -0800376nn::GeneralResult<V1_0::DataLocation> unvalidatedConvert(const nn::DataLocation& dataLocation) {
377 return V1_0::utils::unvalidatedConvert(dataLocation);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800378}
379
Michael Butler6547b2a2020-11-22 19:36:30 -0800380nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
381 const nn::Model::OperandValues& operandValues) {
382 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800383}
384
Michael Butler6547b2a2020-11-22 19:36:30 -0800385nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
386 return V1_2::utils::unvalidatedConvert(handle);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800387}
388
Michael Butler6547b2a2020-11-22 19:36:30 -0800389nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory) {
390 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800391}
392
Michael Butler6547b2a2020-11-22 19:36:30 -0800393nn::GeneralResult<V1_0::RequestArgument> unvalidatedConvert(const nn::Request::Argument& argument) {
394 return V1_0::utils::unvalidatedConvert(argument);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800395}
396
Michael Butler6547b2a2020-11-22 19:36:30 -0800397nn::GeneralResult<V1_2::Operand::ExtraParams> unvalidatedConvert(
398 const nn::Operand::ExtraParams& extraParams) {
399 return V1_2::utils::unvalidatedConvert(extraParams);
400}
401
402nn::GeneralResult<V1_2::Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800403 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800404 return V1_2::utils::unvalidatedConvert(extensionNameAndPrefix);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800405}
406
407template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -0800408using unvalidatedConvertOutput =
409 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800410
411template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800412nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
413 const std::vector<Type>& arguments) {
414 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800415 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800416 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800417 }
418 return halObject;
419}
420
421template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800422nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
423 const std::vector<Type>& arguments) {
424 return unvalidatedConvertVec(arguments);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800425}
426
Michael Butler4b276a72020-08-06 23:22:35 -0700427nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Memory& memory) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800428 Request::MemoryPool ret;
Michael Butler6547b2a2020-11-22 19:36:30 -0800429 ret.hidlMemory(NN_TRY(unvalidatedConvert(memory)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800430 return ret;
431}
432
Michael Butler4b276a72020-08-06 23:22:35 -0700433nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Request::MemoryDomainToken& token) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800434 Request::MemoryPool ret;
435 ret.token(underlyingType(token));
436 return ret;
437}
438
Michael Butler4b276a72020-08-06 23:22:35 -0700439nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::SharedBuffer& /*buffer*/) {
440 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Unable to make memory pool from IBuffer";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800441}
442
Michael Butler6547b2a2020-11-22 19:36:30 -0800443using utils::unvalidatedConvert;
444
445template <typename Type>
446decltype(unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& canonical) {
447 const auto maybeVersion = nn::validate(canonical);
448 if (!maybeVersion.has_value()) {
449 return nn::error() << maybeVersion.error();
450 }
451 const auto version = maybeVersion.value();
452 if (version > kVersion) {
453 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
454 }
455 return unvalidatedConvert(canonical);
456}
457
458template <typename Type>
459nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> validatedConvert(
460 const std::vector<Type>& arguments) {
461 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
462 for (size_t i = 0; i < arguments.size(); ++i) {
463 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
464 }
465 return halObject;
466}
467
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800468} // anonymous namespace
469
Michael Butler6547b2a2020-11-22 19:36:30 -0800470nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800471 return static_cast<OperandType>(operandType);
472}
473
Michael Butler6547b2a2020-11-22 19:36:30 -0800474nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800475 return static_cast<OperationType>(operationType);
476}
477
Michael Butler6547b2a2020-11-22 19:36:30 -0800478nn::GeneralResult<Priority> unvalidatedConvert(const nn::Priority& priority) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800479 return static_cast<Priority>(priority);
480}
481
Michael Butler6547b2a2020-11-22 19:36:30 -0800482nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800483 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
484 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
485 std::copy_if(capabilities.operandPerformance.asVector().begin(),
486 capabilities.operandPerformance.asVector().end(),
487 std::back_inserter(operandPerformance),
488 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
489 return nn::validOperandType(operandPerformance.type);
490 });
491
492 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800493 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
494 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
495 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
496 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
497 .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
498 .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
499 .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800500 };
501}
502
Michael Butler6547b2a2020-11-22 19:36:30 -0800503nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800504 const nn::Capabilities::OperandPerformance& operandPerformance) {
505 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800506 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
507 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800508 };
509}
510
Michael Butler6547b2a2020-11-22 19:36:30 -0800511nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800512 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800513 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800514 .inputs = operation.inputs,
515 .outputs = operation.outputs,
516 };
517}
518
Michael Butler6547b2a2020-11-22 19:36:30 -0800519nn::GeneralResult<OperandLifeTime> unvalidatedConvert(
520 const nn::Operand::LifeTime& operandLifeTime) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800521 if (operandLifeTime == nn::Operand::LifeTime::POINTER) {
Michael Butler4b276a72020-08-06 23:22:35 -0700522 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800523 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800524 }
525 return static_cast<OperandLifeTime>(operandLifeTime);
526}
527
Michael Butler6547b2a2020-11-22 19:36:30 -0800528nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800529 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800530 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800531 .dimensions = operand.dimensions,
532 .numberOfConsumers = 0,
533 .scale = operand.scale,
534 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800535 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
536 .location = NN_TRY(unvalidatedConvert(operand.location)),
537 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800538 };
539}
540
Michael Butler6547b2a2020-11-22 19:36:30 -0800541nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800542 if (!hal::utils::hasNoPointerData(model)) {
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
547 return Model{
Michael Butler6547b2a2020-11-22 19:36:30 -0800548 .main = NN_TRY(unvalidatedConvert(model.main)),
549 .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
550 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
551 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800552 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800553 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800554 };
555}
556
Michael Butler6547b2a2020-11-22 19:36:30 -0800557nn::GeneralResult<Subgraph> unvalidatedConvert(const nn::Model::Subgraph& subgraph) {
558 auto operands = NN_TRY(unvalidatedConvert(subgraph.operands));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800559
560 // Update number of consumers.
561 const auto numberOfConsumers =
562 hal::utils::countNumberOfConsumers(operands.size(), subgraph.operations);
563 CHECK(operands.size() == numberOfConsumers.size());
564 for (size_t i = 0; i < operands.size(); ++i) {
565 operands[i].numberOfConsumers = numberOfConsumers[i];
566 }
567
568 return Subgraph{
569 .operands = std::move(operands),
Michael Butler6547b2a2020-11-22 19:36:30 -0800570 .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800571 .inputIndexes = subgraph.inputIndexes,
572 .outputIndexes = subgraph.outputIndexes,
573 };
574}
575
Michael Butler6547b2a2020-11-22 19:36:30 -0800576nn::GeneralResult<BufferDesc> unvalidatedConvert(const nn::BufferDesc& bufferDesc) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800577 return BufferDesc{.dimensions = bufferDesc.dimensions};
578}
579
Michael Butler6547b2a2020-11-22 19:36:30 -0800580nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRole) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800581 return BufferRole{
582 .modelIndex = bufferRole.modelIndex,
583 .ioIndex = bufferRole.ioIndex,
584 .frequency = bufferRole.frequency,
585 };
586}
587
Michael Butler6547b2a2020-11-22 19:36:30 -0800588nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800589 if (!hal::utils::hasNoPointerData(request)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700590 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800591 << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800592 }
593
594 return Request{
Michael Butler6547b2a2020-11-22 19:36:30 -0800595 .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
596 .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
597 .pools = NN_TRY(unvalidatedConvert(request.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800598 };
599}
600
Michael Butler6547b2a2020-11-22 19:36:30 -0800601nn::GeneralResult<Request::MemoryPool> unvalidatedConvert(
602 const nn::Request::MemoryPool& memoryPool) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800603 return std::visit([](const auto& o) { return makeMemoryPool(o); }, memoryPool);
604}
605
Michael Butler6547b2a2020-11-22 19:36:30 -0800606nn::GeneralResult<OptionalTimePoint> unvalidatedConvert(
607 const nn::OptionalTimePoint& optionalTimePoint) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800608 OptionalTimePoint ret;
609 if (optionalTimePoint.has_value()) {
610 const auto count = optionalTimePoint.value().time_since_epoch().count();
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800611 ret.nanosecondsSinceEpoch(count);
612 }
613 return ret;
614}
615
Michael Butler6547b2a2020-11-22 19:36:30 -0800616nn::GeneralResult<OptionalTimeoutDuration> unvalidatedConvert(
Michael Butler4024d8f2020-12-04 17:38:20 -0800617 const nn::OptionalDuration& optionalTimeoutDuration) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800618 OptionalTimeoutDuration ret;
619 if (optionalTimeoutDuration.has_value()) {
620 const auto count = optionalTimeoutDuration.value().count();
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800621 ret.nanoseconds(count);
622 }
623 return ret;
624}
625
Michael Butler6547b2a2020-11-22 19:36:30 -0800626nn::GeneralResult<ErrorStatus> unvalidatedConvert(const nn::ErrorStatus& errorStatus) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800627 switch (errorStatus) {
628 case nn::ErrorStatus::NONE:
629 case nn::ErrorStatus::DEVICE_UNAVAILABLE:
630 case nn::ErrorStatus::GENERAL_FAILURE:
631 case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
632 case nn::ErrorStatus::INVALID_ARGUMENT:
633 case nn::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
634 case nn::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
635 case nn::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
636 case nn::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
637 return static_cast<ErrorStatus>(errorStatus);
638 default:
639 return ErrorStatus::GENERAL_FAILURE;
640 }
641}
642
Michael Butler6547b2a2020-11-22 19:36:30 -0800643nn::GeneralResult<Priority> convert(const nn::Priority& priority) {
644 return validatedConvert(priority);
645}
646
647nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
648 return validatedConvert(capabilities);
649}
650
651nn::GeneralResult<Model> convert(const nn::Model& model) {
652 return validatedConvert(model);
653}
654
655nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc) {
656 return validatedConvert(bufferDesc);
657}
658
659nn::GeneralResult<Request> convert(const nn::Request& request) {
660 return validatedConvert(request);
661}
662
663nn::GeneralResult<OptionalTimePoint> convert(const nn::OptionalTimePoint& optionalTimePoint) {
664 return validatedConvert(optionalTimePoint);
665}
666
667nn::GeneralResult<OptionalTimeoutDuration> convert(
Michael Butler4024d8f2020-12-04 17:38:20 -0800668 const nn::OptionalDuration& optionalTimeoutDuration) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800669 return validatedConvert(optionalTimeoutDuration);
670}
671
672nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus) {
673 return validatedConvert(errorStatus);
674}
675
676nn::GeneralResult<hidl_handle> convert(const nn::SharedHandle& handle) {
677 return validatedConvert(handle);
678}
679
680nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory) {
681 return validatedConvert(memory);
682}
683
Michael Butler4b276a72020-08-06 23:22:35 -0700684nn::GeneralResult<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800685 return validatedConvert(bufferRoles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800686}
687
Michael Butler7fd03c22020-12-06 21:50:59 -0800688nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
689 return V1_2::utils::convert(deviceStatus);
690}
691
692nn::GeneralResult<V1_1::ExecutionPreference> convert(
693 const nn::ExecutionPreference& executionPreference) {
694 return V1_2::utils::convert(executionPreference);
695}
696
697nn::GeneralResult<hidl_vec<V1_2::Extension>> convert(const std::vector<nn::Extension>& extensions) {
698 return V1_2::utils::convert(extensions);
699}
700
701nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
702 return V1_2::utils::convert(handles);
703}
704
705nn::GeneralResult<hidl_vec<V1_2::OutputShape>> convert(
706 const std::vector<nn::OutputShape>& outputShapes) {
707 return V1_2::utils::convert(outputShapes);
708}
709
710nn::GeneralResult<V1_2::DeviceType> convert(const nn::DeviceType& deviceType) {
711 return V1_2::utils::convert(deviceType);
712}
713
714nn::GeneralResult<V1_2::MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
715 return V1_2::utils::convert(measureTiming);
716}
717
718nn::GeneralResult<V1_2::Timing> convert(const nn::Timing& timing) {
719 return V1_2::utils::convert(timing);
720}
721
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800722} // namespace android::hardware::neuralnetworks::V1_3::utils