blob: 8b45f715abebac4024cd0fd68fc6c0e4d9ab42b3 [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 =
Michael Butler68b69262021-02-09 15:36:11 -0800220 NN_TRY(hal::utils::countNumberOfConsumers(subgraph.operands.size(), operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800221 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,
Xusong Wang3633d072021-03-19 13:58:24 -0700247 .probability = bufferRole.frequency,
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800248 };
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:
Michael Butlerab2f4822021-02-08 00:05:07 -0800264 return hal::utils::createSharedMemoryFromHidlMemory(memoryPool.hidlMemory());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800265 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
Michael Butler4b276a72020-08-06 23:22:35 -0700355GeneralResult<std::vector<BufferRole>> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800356 const hardware::hidl_vec<hal::V1_3::BufferRole>& bufferRoles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800357 return validatedConvert(bufferRoles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800358}
359
360} // namespace android::nn
361
362namespace android::hardware::neuralnetworks::V1_3::utils {
363namespace {
364
Michael Butler6547b2a2020-11-22 19:36:30 -0800365using utils::unvalidatedConvert;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800366
Michael Butler6547b2a2020-11-22 19:36:30 -0800367nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800368 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800369 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800370}
371
Michael Butler6547b2a2020-11-22 19:36:30 -0800372nn::GeneralResult<V1_0::DataLocation> unvalidatedConvert(const nn::DataLocation& dataLocation) {
373 return V1_0::utils::unvalidatedConvert(dataLocation);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800374}
375
Michael Butler6547b2a2020-11-22 19:36:30 -0800376nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
377 const nn::Model::OperandValues& operandValues) {
378 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800379}
380
Michael Butler6547b2a2020-11-22 19:36:30 -0800381nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
382 return V1_2::utils::unvalidatedConvert(handle);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800383}
384
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800385nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800386 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800387}
388
Michael Butler6547b2a2020-11-22 19:36:30 -0800389nn::GeneralResult<V1_0::RequestArgument> unvalidatedConvert(const nn::Request::Argument& argument) {
390 return V1_0::utils::unvalidatedConvert(argument);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800391}
392
Michael Butler6547b2a2020-11-22 19:36:30 -0800393nn::GeneralResult<V1_2::Operand::ExtraParams> unvalidatedConvert(
394 const nn::Operand::ExtraParams& extraParams) {
395 return V1_2::utils::unvalidatedConvert(extraParams);
396}
397
398nn::GeneralResult<V1_2::Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800399 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800400 return V1_2::utils::unvalidatedConvert(extensionNameAndPrefix);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800401}
402
403template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -0800404using unvalidatedConvertOutput =
405 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800406
407template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800408nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
409 const std::vector<Type>& arguments) {
410 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800411 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800412 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800413 }
414 return halObject;
415}
416
417template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800418nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
419 const std::vector<Type>& arguments) {
420 return unvalidatedConvertVec(arguments);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800421}
422
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800423nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::SharedMemory& memory) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800424 Request::MemoryPool ret;
Michael Butler6547b2a2020-11-22 19:36:30 -0800425 ret.hidlMemory(NN_TRY(unvalidatedConvert(memory)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800426 return ret;
427}
428
Michael Butler4b276a72020-08-06 23:22:35 -0700429nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Request::MemoryDomainToken& token) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800430 Request::MemoryPool ret;
431 ret.token(underlyingType(token));
432 return ret;
433}
434
Michael Butler4b276a72020-08-06 23:22:35 -0700435nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::SharedBuffer& /*buffer*/) {
436 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Unable to make memory pool from IBuffer";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800437}
438
Michael Butler6547b2a2020-11-22 19:36:30 -0800439using utils::unvalidatedConvert;
440
441template <typename Type>
442decltype(unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& canonical) {
443 const auto maybeVersion = nn::validate(canonical);
444 if (!maybeVersion.has_value()) {
445 return nn::error() << maybeVersion.error();
446 }
447 const auto version = maybeVersion.value();
448 if (version > kVersion) {
449 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
450 }
451 return unvalidatedConvert(canonical);
452}
453
454template <typename Type>
455nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> validatedConvert(
456 const std::vector<Type>& arguments) {
457 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
458 for (size_t i = 0; i < arguments.size(); ++i) {
459 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
460 }
461 return halObject;
462}
463
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800464} // anonymous namespace
465
Michael Butler6547b2a2020-11-22 19:36:30 -0800466nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800467 return static_cast<OperandType>(operandType);
468}
469
Michael Butler6547b2a2020-11-22 19:36:30 -0800470nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800471 return static_cast<OperationType>(operationType);
472}
473
Michael Butler6547b2a2020-11-22 19:36:30 -0800474nn::GeneralResult<Priority> unvalidatedConvert(const nn::Priority& priority) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800475 return static_cast<Priority>(priority);
476}
477
Michael Butler6547b2a2020-11-22 19:36:30 -0800478nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800479 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
480 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
481 std::copy_if(capabilities.operandPerformance.asVector().begin(),
482 capabilities.operandPerformance.asVector().end(),
483 std::back_inserter(operandPerformance),
484 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
485 return nn::validOperandType(operandPerformance.type);
486 });
487
488 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800489 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
490 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
491 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
492 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
493 .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
494 .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
495 .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800496 };
497}
498
Michael Butler6547b2a2020-11-22 19:36:30 -0800499nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800500 const nn::Capabilities::OperandPerformance& operandPerformance) {
501 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800502 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
503 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800504 };
505}
506
Michael Butler6547b2a2020-11-22 19:36:30 -0800507nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800508 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800509 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800510 .inputs = operation.inputs,
511 .outputs = operation.outputs,
512 };
513}
514
Michael Butler6547b2a2020-11-22 19:36:30 -0800515nn::GeneralResult<OperandLifeTime> unvalidatedConvert(
516 const nn::Operand::LifeTime& operandLifeTime) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800517 if (operandLifeTime == nn::Operand::LifeTime::POINTER) {
Michael Butler4b276a72020-08-06 23:22:35 -0700518 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800519 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800520 }
521 return static_cast<OperandLifeTime>(operandLifeTime);
522}
523
Michael Butler6547b2a2020-11-22 19:36:30 -0800524nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800525 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800526 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800527 .dimensions = operand.dimensions,
528 .numberOfConsumers = 0,
529 .scale = operand.scale,
530 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800531 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
532 .location = NN_TRY(unvalidatedConvert(operand.location)),
533 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800534 };
535}
536
Michael Butler6547b2a2020-11-22 19:36:30 -0800537nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800538 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700539 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800540 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800541 }
542
543 return Model{
Michael Butler6547b2a2020-11-22 19:36:30 -0800544 .main = NN_TRY(unvalidatedConvert(model.main)),
545 .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
546 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
547 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800548 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800549 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800550 };
551}
552
Michael Butler6547b2a2020-11-22 19:36:30 -0800553nn::GeneralResult<Subgraph> unvalidatedConvert(const nn::Model::Subgraph& subgraph) {
554 auto operands = NN_TRY(unvalidatedConvert(subgraph.operands));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800555
556 // Update number of consumers.
557 const auto numberOfConsumers =
Michael Butler68b69262021-02-09 15:36:11 -0800558 NN_TRY(hal::utils::countNumberOfConsumers(operands.size(), subgraph.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800559 CHECK(operands.size() == numberOfConsumers.size());
560 for (size_t i = 0; i < operands.size(); ++i) {
561 operands[i].numberOfConsumers = numberOfConsumers[i];
562 }
563
564 return Subgraph{
565 .operands = std::move(operands),
Michael Butler6547b2a2020-11-22 19:36:30 -0800566 .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800567 .inputIndexes = subgraph.inputIndexes,
568 .outputIndexes = subgraph.outputIndexes,
569 };
570}
571
Michael Butler6547b2a2020-11-22 19:36:30 -0800572nn::GeneralResult<BufferDesc> unvalidatedConvert(const nn::BufferDesc& bufferDesc) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800573 return BufferDesc{.dimensions = bufferDesc.dimensions};
574}
575
Michael Butler6547b2a2020-11-22 19:36:30 -0800576nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRole) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800577 return BufferRole{
578 .modelIndex = bufferRole.modelIndex,
579 .ioIndex = bufferRole.ioIndex,
Xusong Wang3633d072021-03-19 13:58:24 -0700580 .frequency = bufferRole.probability,
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800581 };
582}
583
Michael Butler6547b2a2020-11-22 19:36:30 -0800584nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800585 if (!hal::utils::hasNoPointerData(request)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700586 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800587 << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800588 }
589
590 return Request{
Michael Butler6547b2a2020-11-22 19:36:30 -0800591 .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
592 .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
593 .pools = NN_TRY(unvalidatedConvert(request.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800594 };
595}
596
Michael Butler6547b2a2020-11-22 19:36:30 -0800597nn::GeneralResult<Request::MemoryPool> unvalidatedConvert(
598 const nn::Request::MemoryPool& memoryPool) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800599 return std::visit([](const auto& o) { return makeMemoryPool(o); }, memoryPool);
600}
601
Michael Butler6547b2a2020-11-22 19:36:30 -0800602nn::GeneralResult<OptionalTimePoint> unvalidatedConvert(
603 const nn::OptionalTimePoint& optionalTimePoint) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800604 OptionalTimePoint ret;
605 if (optionalTimePoint.has_value()) {
606 const auto count = optionalTimePoint.value().time_since_epoch().count();
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800607 ret.nanosecondsSinceEpoch(count);
608 }
609 return ret;
610}
611
Michael Butler6547b2a2020-11-22 19:36:30 -0800612nn::GeneralResult<OptionalTimeoutDuration> unvalidatedConvert(
Michael Butler4024d8f2020-12-04 17:38:20 -0800613 const nn::OptionalDuration& optionalTimeoutDuration) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800614 OptionalTimeoutDuration ret;
615 if (optionalTimeoutDuration.has_value()) {
616 const auto count = optionalTimeoutDuration.value().count();
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800617 ret.nanoseconds(count);
618 }
619 return ret;
620}
621
Michael Butler6547b2a2020-11-22 19:36:30 -0800622nn::GeneralResult<ErrorStatus> unvalidatedConvert(const nn::ErrorStatus& errorStatus) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800623 switch (errorStatus) {
624 case nn::ErrorStatus::NONE:
625 case nn::ErrorStatus::DEVICE_UNAVAILABLE:
626 case nn::ErrorStatus::GENERAL_FAILURE:
627 case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
628 case nn::ErrorStatus::INVALID_ARGUMENT:
629 case nn::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
630 case nn::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
631 case nn::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
632 case nn::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
633 return static_cast<ErrorStatus>(errorStatus);
634 default:
635 return ErrorStatus::GENERAL_FAILURE;
636 }
637}
638
Michael Butler6547b2a2020-11-22 19:36:30 -0800639nn::GeneralResult<Priority> convert(const nn::Priority& priority) {
640 return validatedConvert(priority);
641}
642
643nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
644 return validatedConvert(capabilities);
645}
646
647nn::GeneralResult<Model> convert(const nn::Model& model) {
648 return validatedConvert(model);
649}
650
651nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc) {
652 return validatedConvert(bufferDesc);
653}
654
655nn::GeneralResult<Request> convert(const nn::Request& request) {
656 return validatedConvert(request);
657}
658
659nn::GeneralResult<OptionalTimePoint> convert(const nn::OptionalTimePoint& optionalTimePoint) {
660 return validatedConvert(optionalTimePoint);
661}
662
663nn::GeneralResult<OptionalTimeoutDuration> convert(
Michael Butler4024d8f2020-12-04 17:38:20 -0800664 const nn::OptionalDuration& optionalTimeoutDuration) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800665 return validatedConvert(optionalTimeoutDuration);
666}
667
668nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus) {
669 return validatedConvert(errorStatus);
670}
671
672nn::GeneralResult<hidl_handle> convert(const nn::SharedHandle& handle) {
673 return validatedConvert(handle);
674}
675
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800676nn::GeneralResult<hidl_memory> convert(const nn::SharedMemory& memory) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800677 return validatedConvert(memory);
678}
679
Michael Butler4b276a72020-08-06 23:22:35 -0700680nn::GeneralResult<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800681 return validatedConvert(bufferRoles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800682}
683
Michael Butler7fd03c22020-12-06 21:50:59 -0800684nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
685 return V1_2::utils::convert(deviceStatus);
686}
687
688nn::GeneralResult<V1_1::ExecutionPreference> convert(
689 const nn::ExecutionPreference& executionPreference) {
690 return V1_2::utils::convert(executionPreference);
691}
692
693nn::GeneralResult<hidl_vec<V1_2::Extension>> convert(const std::vector<nn::Extension>& extensions) {
694 return V1_2::utils::convert(extensions);
695}
696
697nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
698 return V1_2::utils::convert(handles);
699}
700
701nn::GeneralResult<hidl_vec<V1_2::OutputShape>> convert(
702 const std::vector<nn::OutputShape>& outputShapes) {
703 return V1_2::utils::convert(outputShapes);
704}
705
706nn::GeneralResult<V1_2::DeviceType> convert(const nn::DeviceType& deviceType) {
707 return V1_2::utils::convert(deviceType);
708}
709
710nn::GeneralResult<V1_2::MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
711 return V1_2::utils::convert(measureTiming);
712}
713
714nn::GeneralResult<V1_2::Timing> convert(const nn::Timing& timing) {
715 return V1_2::utils::convert(timing);
716}
717
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800718} // namespace android::hardware::neuralnetworks::V1_3::utils