blob: 0dc078534c7b5f0ee0e3992608511a700fd8a5f0 [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>
27#include <nnapi/hal/1.0/Conversions.h>
28#include <nnapi/hal/1.2/Conversions.h>
29#include <nnapi/hal/CommonUtils.h>
Michael Butler4b276a72020-08-06 23:22:35 -070030#include <nnapi/hal/HandleError.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080031
32#include <algorithm>
33#include <chrono>
34#include <functional>
35#include <iterator>
36#include <limits>
37#include <type_traits>
38#include <utility>
39
40namespace {
41
42template <typename Type>
43constexpr std::underlying_type_t<Type> underlyingType(Type value) {
44 return static_cast<std::underlying_type_t<Type>>(value);
45}
46
47} // namespace
48
49namespace android::nn {
50namespace {
51
52constexpr auto validOperandType(nn::OperandType operandType) {
53 switch (operandType) {
54 case nn::OperandType::FLOAT32:
55 case nn::OperandType::INT32:
56 case nn::OperandType::UINT32:
57 case nn::OperandType::TENSOR_FLOAT32:
58 case nn::OperandType::TENSOR_INT32:
59 case nn::OperandType::TENSOR_QUANT8_ASYMM:
60 case nn::OperandType::BOOL:
61 case nn::OperandType::TENSOR_QUANT16_SYMM:
62 case nn::OperandType::TENSOR_FLOAT16:
63 case nn::OperandType::TENSOR_BOOL8:
64 case nn::OperandType::FLOAT16:
65 case nn::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
66 case nn::OperandType::TENSOR_QUANT16_ASYMM:
67 case nn::OperandType::TENSOR_QUANT8_SYMM:
68 case nn::OperandType::TENSOR_QUANT8_ASYMM_SIGNED:
69 case nn::OperandType::SUBGRAPH:
70 case nn::OperandType::OEM:
71 case nn::OperandType::TENSOR_OEM_BYTE:
72 return true;
73 }
74 return nn::isExtension(operandType);
75}
76
77using hardware::hidl_vec;
78
79template <typename Input>
80using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
81
82template <typename Type>
Michael Butler4b276a72020-08-06 23:22:35 -070083GeneralResult<std::vector<ConvertOutput<Type>>> convertVec(const hidl_vec<Type>& arguments) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -080084 std::vector<ConvertOutput<Type>> canonical;
85 canonical.reserve(arguments.size());
86 for (const auto& argument : arguments) {
87 canonical.push_back(NN_TRY(nn::convert(argument)));
88 }
89 return canonical;
90}
91
92template <typename Type>
Michael Butler4b276a72020-08-06 23:22:35 -070093GeneralResult<std::vector<ConvertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -080094 return convertVec(arguments);
95}
96
97} // anonymous namespace
98
Michael Butler4b276a72020-08-06 23:22:35 -070099GeneralResult<OperandType> convert(const hal::V1_3::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800100 return static_cast<OperandType>(operandType);
101}
102
Michael Butler4b276a72020-08-06 23:22:35 -0700103GeneralResult<OperationType> convert(const hal::V1_3::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800104 return static_cast<OperationType>(operationType);
105}
106
Michael Butler4b276a72020-08-06 23:22:35 -0700107GeneralResult<Priority> convert(const hal::V1_3::Priority& priority) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800108 return static_cast<Priority>(priority);
109}
110
Michael Butler4b276a72020-08-06 23:22:35 -0700111GeneralResult<Capabilities> convert(const hal::V1_3::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800112 const bool validOperandTypes = std::all_of(
113 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
114 [](const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) {
115 const auto maybeType = convert(operandPerformance.type);
116 return !maybeType.has_value() ? false : validOperandType(maybeType.value());
117 });
118 if (!validOperandTypes) {
Michael Butler4b276a72020-08-06 23:22:35 -0700119 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800120 << "Invalid OperandType when converting OperandPerformance in Capabilities";
121 }
122
123 auto operandPerformance = NN_TRY(convert(capabilities.operandPerformance));
Michael Butler4b276a72020-08-06 23:22:35 -0700124 auto table = NN_TRY(hal::utils::makeGeneralFailure(
125 Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
126 nn::ErrorStatus::GENERAL_FAILURE));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800127
128 return Capabilities{
129 .relaxedFloat32toFloat16PerformanceScalar =
130 NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
131 .relaxedFloat32toFloat16PerformanceTensor =
132 NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
133 .operandPerformance = std::move(table),
134 .ifPerformance = NN_TRY(convert(capabilities.ifPerformance)),
135 .whilePerformance = NN_TRY(convert(capabilities.whilePerformance)),
136 };
137}
138
Michael Butler4b276a72020-08-06 23:22:35 -0700139GeneralResult<Capabilities::OperandPerformance> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800140 const hal::V1_3::Capabilities::OperandPerformance& operandPerformance) {
141 return Capabilities::OperandPerformance{
142 .type = NN_TRY(convert(operandPerformance.type)),
143 .info = NN_TRY(convert(operandPerformance.info)),
144 };
145}
146
Michael Butler4b276a72020-08-06 23:22:35 -0700147GeneralResult<Operation> convert(const hal::V1_3::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800148 return Operation{
149 .type = NN_TRY(convert(operation.type)),
150 .inputs = operation.inputs,
151 .outputs = operation.outputs,
152 };
153}
154
Michael Butler4b276a72020-08-06 23:22:35 -0700155GeneralResult<Operand::LifeTime> convert(const hal::V1_3::OperandLifeTime& operandLifeTime) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800156 return static_cast<Operand::LifeTime>(operandLifeTime);
157}
158
Michael Butler4b276a72020-08-06 23:22:35 -0700159GeneralResult<Operand> convert(const hal::V1_3::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800160 return Operand{
161 .type = NN_TRY(convert(operand.type)),
162 .dimensions = operand.dimensions,
163 .scale = operand.scale,
164 .zeroPoint = operand.zeroPoint,
165 .lifetime = NN_TRY(convert(operand.lifetime)),
166 .location = NN_TRY(convert(operand.location)),
167 .extraParams = NN_TRY(convert(operand.extraParams)),
168 };
169}
170
Michael Butler4b276a72020-08-06 23:22:35 -0700171GeneralResult<Model> convert(const hal::V1_3::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800172 return Model{
173 .main = NN_TRY(convert(model.main)),
174 .referenced = NN_TRY(convert(model.referenced)),
175 .operandValues = NN_TRY(convert(model.operandValues)),
176 .pools = NN_TRY(convert(model.pools)),
177 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
178 .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
179 };
180}
181
Michael Butler4b276a72020-08-06 23:22:35 -0700182GeneralResult<Model::Subgraph> convert(const hal::V1_3::Subgraph& subgraph) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800183 auto operations = NN_TRY(convert(subgraph.operations));
184
185 // Verify number of consumers.
186 const auto numberOfConsumers =
187 hal::utils::countNumberOfConsumers(subgraph.operands.size(), operations);
188 CHECK(subgraph.operands.size() == numberOfConsumers.size());
189 for (size_t i = 0; i < subgraph.operands.size(); ++i) {
190 if (subgraph.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler4b276a72020-08-06 23:22:35 -0700191 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
192 << "Invalid numberOfConsumers for operand " << i << ", expected "
193 << numberOfConsumers[i] << " but found "
194 << subgraph.operands[i].numberOfConsumers;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800195 }
196 }
197
198 return Model::Subgraph{
199 .operands = NN_TRY(convert(subgraph.operands)),
200 .operations = std::move(operations),
201 .inputIndexes = subgraph.inputIndexes,
202 .outputIndexes = subgraph.outputIndexes,
203 };
204}
205
Michael Butler4b276a72020-08-06 23:22:35 -0700206GeneralResult<BufferDesc> convert(const hal::V1_3::BufferDesc& bufferDesc) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800207 return BufferDesc{.dimensions = bufferDesc.dimensions};
208}
209
Michael Butler4b276a72020-08-06 23:22:35 -0700210GeneralResult<BufferRole> convert(const hal::V1_3::BufferRole& bufferRole) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800211 return BufferRole{
212 .modelIndex = bufferRole.modelIndex,
213 .ioIndex = bufferRole.ioIndex,
214 .frequency = bufferRole.frequency,
215 };
216}
217
Michael Butler4b276a72020-08-06 23:22:35 -0700218GeneralResult<Request> convert(const hal::V1_3::Request& request) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800219 return Request{
220 .inputs = NN_TRY(convert(request.inputs)),
221 .outputs = NN_TRY(convert(request.outputs)),
222 .pools = NN_TRY(convert(request.pools)),
223 };
224}
225
Michael Butler4b276a72020-08-06 23:22:35 -0700226GeneralResult<Request::MemoryPool> convert(const hal::V1_3::Request::MemoryPool& memoryPool) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800227 using Discriminator = hal::V1_3::Request::MemoryPool::hidl_discriminator;
228 switch (memoryPool.getDiscriminator()) {
229 case Discriminator::hidlMemory:
230 return createSharedMemoryFromHidlMemory(memoryPool.hidlMemory());
231 case Discriminator::token:
232 return static_cast<Request::MemoryDomainToken>(memoryPool.token());
233 }
Michael Butler4b276a72020-08-06 23:22:35 -0700234 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
235 << "Invalid Request::MemoryPool discriminator "
236 << underlyingType(memoryPool.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800237}
238
Michael Butler4b276a72020-08-06 23:22:35 -0700239GeneralResult<OptionalTimePoint> convert(const hal::V1_3::OptionalTimePoint& optionalTimePoint) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800240 constexpr auto kTimePointMaxCount = TimePoint::max().time_since_epoch().count();
Michael Butler4b276a72020-08-06 23:22:35 -0700241 const auto makeTimePoint = [](uint64_t count) -> GeneralResult<OptionalTimePoint> {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800242 if (count > kTimePointMaxCount) {
Michael Butler4b276a72020-08-06 23:22:35 -0700243 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800244 << "Unable to convert OptionalTimePoint because the count exceeds the max";
245 }
246 const auto nanoseconds = std::chrono::nanoseconds{count};
247 return TimePoint{nanoseconds};
248 };
249
250 using Discriminator = hal::V1_3::OptionalTimePoint::hidl_discriminator;
251 switch (optionalTimePoint.getDiscriminator()) {
252 case Discriminator::none:
253 return std::nullopt;
254 case Discriminator::nanosecondsSinceEpoch:
255 return makeTimePoint(optionalTimePoint.nanosecondsSinceEpoch());
256 }
Michael Butler4b276a72020-08-06 23:22:35 -0700257 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
258 << "Invalid OptionalTimePoint discriminator "
259 << underlyingType(optionalTimePoint.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800260}
261
Michael Butler4b276a72020-08-06 23:22:35 -0700262GeneralResult<OptionalTimeoutDuration> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800263 const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration) {
264 constexpr auto kTimeoutDurationMaxCount = TimeoutDuration::max().count();
Michael Butler4b276a72020-08-06 23:22:35 -0700265 const auto makeTimeoutDuration = [](uint64_t count) -> GeneralResult<OptionalTimeoutDuration> {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800266 if (count > kTimeoutDurationMaxCount) {
Michael Butler4b276a72020-08-06 23:22:35 -0700267 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800268 << "Unable to convert OptionalTimeoutDuration because the count exceeds the max";
269 }
270 return TimeoutDuration{count};
271 };
272
273 using Discriminator = hal::V1_3::OptionalTimeoutDuration::hidl_discriminator;
274 switch (optionalTimeoutDuration.getDiscriminator()) {
275 case Discriminator::none:
276 return std::nullopt;
277 case Discriminator::nanoseconds:
278 return makeTimeoutDuration(optionalTimeoutDuration.nanoseconds());
279 }
Michael Butler4b276a72020-08-06 23:22:35 -0700280 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
281 << "Invalid OptionalTimeoutDuration discriminator "
282 << underlyingType(optionalTimeoutDuration.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800283}
284
Michael Butler4b276a72020-08-06 23:22:35 -0700285GeneralResult<ErrorStatus> convert(const hal::V1_3::ErrorStatus& status) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800286 switch (status) {
287 case hal::V1_3::ErrorStatus::NONE:
288 case hal::V1_3::ErrorStatus::DEVICE_UNAVAILABLE:
289 case hal::V1_3::ErrorStatus::GENERAL_FAILURE:
290 case hal::V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
291 case hal::V1_3::ErrorStatus::INVALID_ARGUMENT:
292 case hal::V1_3::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
293 case hal::V1_3::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
294 case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
295 case hal::V1_3::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
296 return static_cast<ErrorStatus>(status);
297 }
Michael Butler4b276a72020-08-06 23:22:35 -0700298 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
299 << "Invalid ErrorStatus " << underlyingType(status);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800300}
301
Michael Butler4b276a72020-08-06 23:22:35 -0700302GeneralResult<std::vector<BufferRole>> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800303 const hardware::hidl_vec<hal::V1_3::BufferRole>& bufferRoles) {
304 return convertVec(bufferRoles);
305}
306
307} // namespace android::nn
308
309namespace android::hardware::neuralnetworks::V1_3::utils {
310namespace {
311
312using utils::convert;
313
Michael Butler4b276a72020-08-06 23:22:35 -0700314nn::GeneralResult<V1_0::PerformanceInfo> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800315 const nn::Capabilities::PerformanceInfo& performanceInfo) {
316 return V1_0::utils::convert(performanceInfo);
317}
318
Michael Butler4b276a72020-08-06 23:22:35 -0700319nn::GeneralResult<V1_0::DataLocation> convert(const nn::DataLocation& dataLocation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800320 return V1_0::utils::convert(dataLocation);
321}
322
Michael Butler4b276a72020-08-06 23:22:35 -0700323nn::GeneralResult<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800324 return V1_0::utils::convert(operandValues);
325}
326
Michael Butler4b276a72020-08-06 23:22:35 -0700327nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800328 return V1_0::utils::convert(memory);
329}
330
Michael Butler4b276a72020-08-06 23:22:35 -0700331nn::GeneralResult<V1_0::RequestArgument> convert(const nn::Request::Argument& argument) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800332 return V1_0::utils::convert(argument);
333}
334
Michael Butler4b276a72020-08-06 23:22:35 -0700335nn::GeneralResult<V1_2::Operand::ExtraParams> convert(const nn::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800336 return V1_2::utils::convert(extraParams);
337}
338
Michael Butler4b276a72020-08-06 23:22:35 -0700339nn::GeneralResult<V1_2::Model::ExtensionNameAndPrefix> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800340 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
341 return V1_2::utils::convert(extensionNameAndPrefix);
342}
343
344template <typename Input>
345using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
346
347template <typename Type>
Michael Butler4b276a72020-08-06 23:22:35 -0700348nn::GeneralResult<hidl_vec<ConvertOutput<Type>>> convertVec(const std::vector<Type>& arguments) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800349 hidl_vec<ConvertOutput<Type>> halObject(arguments.size());
350 for (size_t i = 0; i < arguments.size(); ++i) {
351 halObject[i] = NN_TRY(convert(arguments[i]));
352 }
353 return halObject;
354}
355
356template <typename Type>
Michael Butler4b276a72020-08-06 23:22:35 -0700357nn::GeneralResult<hidl_vec<ConvertOutput<Type>>> convert(const std::vector<Type>& arguments) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800358 return convertVec(arguments);
359}
360
Michael Butler4b276a72020-08-06 23:22:35 -0700361nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Memory& memory) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800362 Request::MemoryPool ret;
363 ret.hidlMemory(NN_TRY(convert(memory)));
364 return ret;
365}
366
Michael Butler4b276a72020-08-06 23:22:35 -0700367nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::Request::MemoryDomainToken& token) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800368 Request::MemoryPool ret;
369 ret.token(underlyingType(token));
370 return ret;
371}
372
Michael Butler4b276a72020-08-06 23:22:35 -0700373nn::GeneralResult<Request::MemoryPool> makeMemoryPool(const nn::SharedBuffer& /*buffer*/) {
374 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Unable to make memory pool from IBuffer";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800375}
376
377} // anonymous namespace
378
Michael Butler4b276a72020-08-06 23:22:35 -0700379nn::GeneralResult<OperandType> convert(const nn::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800380 return static_cast<OperandType>(operandType);
381}
382
Michael Butler4b276a72020-08-06 23:22:35 -0700383nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800384 return static_cast<OperationType>(operationType);
385}
386
Michael Butler4b276a72020-08-06 23:22:35 -0700387nn::GeneralResult<Priority> convert(const nn::Priority& priority) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800388 return static_cast<Priority>(priority);
389}
390
Michael Butler4b276a72020-08-06 23:22:35 -0700391nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800392 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
393 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
394 std::copy_if(capabilities.operandPerformance.asVector().begin(),
395 capabilities.operandPerformance.asVector().end(),
396 std::back_inserter(operandPerformance),
397 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
398 return nn::validOperandType(operandPerformance.type);
399 });
400
401 return Capabilities{
402 .relaxedFloat32toFloat16PerformanceScalar =
403 NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
404 .relaxedFloat32toFloat16PerformanceTensor =
405 NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
406 .operandPerformance = NN_TRY(convert(operandPerformance)),
407 .ifPerformance = NN_TRY(convert(capabilities.ifPerformance)),
408 .whilePerformance = NN_TRY(convert(capabilities.whilePerformance)),
409 };
410}
411
Michael Butler4b276a72020-08-06 23:22:35 -0700412nn::GeneralResult<Capabilities::OperandPerformance> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800413 const nn::Capabilities::OperandPerformance& operandPerformance) {
414 return Capabilities::OperandPerformance{
415 .type = NN_TRY(convert(operandPerformance.type)),
416 .info = NN_TRY(convert(operandPerformance.info)),
417 };
418}
419
Michael Butler4b276a72020-08-06 23:22:35 -0700420nn::GeneralResult<Operation> convert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800421 return Operation{
422 .type = NN_TRY(convert(operation.type)),
423 .inputs = operation.inputs,
424 .outputs = operation.outputs,
425 };
426}
427
Michael Butler4b276a72020-08-06 23:22:35 -0700428nn::GeneralResult<OperandLifeTime> convert(const nn::Operand::LifeTime& operandLifeTime) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800429 if (operandLifeTime == nn::Operand::LifeTime::POINTER) {
Michael Butler4b276a72020-08-06 23:22:35 -0700430 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
431 << "Model cannot be converted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800432 }
433 return static_cast<OperandLifeTime>(operandLifeTime);
434}
435
Michael Butler4b276a72020-08-06 23:22:35 -0700436nn::GeneralResult<Operand> convert(const nn::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800437 return Operand{
438 .type = NN_TRY(convert(operand.type)),
439 .dimensions = operand.dimensions,
440 .numberOfConsumers = 0,
441 .scale = operand.scale,
442 .zeroPoint = operand.zeroPoint,
443 .lifetime = NN_TRY(convert(operand.lifetime)),
444 .location = NN_TRY(convert(operand.location)),
445 .extraParams = NN_TRY(convert(operand.extraParams)),
446 };
447}
448
Michael Butler4b276a72020-08-06 23:22:35 -0700449nn::GeneralResult<Model> convert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800450 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700451 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
452 << "Model cannot be converted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800453 }
454
455 return Model{
456 .main = NN_TRY(convert(model.main)),
457 .referenced = NN_TRY(convert(model.referenced)),
458 .operandValues = NN_TRY(convert(model.operandValues)),
459 .pools = NN_TRY(convert(model.pools)),
460 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
461 .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
462 };
463}
464
Michael Butler4b276a72020-08-06 23:22:35 -0700465nn::GeneralResult<Subgraph> convert(const nn::Model::Subgraph& subgraph) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800466 auto operands = NN_TRY(convert(subgraph.operands));
467
468 // Update number of consumers.
469 const auto numberOfConsumers =
470 hal::utils::countNumberOfConsumers(operands.size(), subgraph.operations);
471 CHECK(operands.size() == numberOfConsumers.size());
472 for (size_t i = 0; i < operands.size(); ++i) {
473 operands[i].numberOfConsumers = numberOfConsumers[i];
474 }
475
476 return Subgraph{
477 .operands = std::move(operands),
478 .operations = NN_TRY(convert(subgraph.operations)),
479 .inputIndexes = subgraph.inputIndexes,
480 .outputIndexes = subgraph.outputIndexes,
481 };
482}
483
Michael Butler4b276a72020-08-06 23:22:35 -0700484nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800485 return BufferDesc{.dimensions = bufferDesc.dimensions};
486}
487
Michael Butler4b276a72020-08-06 23:22:35 -0700488nn::GeneralResult<BufferRole> convert(const nn::BufferRole& bufferRole) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800489 return BufferRole{
490 .modelIndex = bufferRole.modelIndex,
491 .ioIndex = bufferRole.ioIndex,
492 .frequency = bufferRole.frequency,
493 };
494}
495
Michael Butler4b276a72020-08-06 23:22:35 -0700496nn::GeneralResult<Request> convert(const nn::Request& request) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800497 if (!hal::utils::hasNoPointerData(request)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700498 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
499 << "Request cannot be converted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800500 }
501
502 return Request{
503 .inputs = NN_TRY(convert(request.inputs)),
504 .outputs = NN_TRY(convert(request.outputs)),
505 .pools = NN_TRY(convert(request.pools)),
506 };
507}
508
Michael Butler4b276a72020-08-06 23:22:35 -0700509nn::GeneralResult<Request::MemoryPool> convert(const nn::Request::MemoryPool& memoryPool) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800510 return std::visit([](const auto& o) { return makeMemoryPool(o); }, memoryPool);
511}
512
Michael Butler4b276a72020-08-06 23:22:35 -0700513nn::GeneralResult<OptionalTimePoint> convert(const nn::OptionalTimePoint& optionalTimePoint) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800514 OptionalTimePoint ret;
515 if (optionalTimePoint.has_value()) {
516 const auto count = optionalTimePoint.value().time_since_epoch().count();
517 if (count < 0) {
Michael Butler4b276a72020-08-06 23:22:35 -0700518 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
519 << "Unable to convert OptionalTimePoint because time since epoch count is "
520 "negative";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800521 }
522 ret.nanosecondsSinceEpoch(count);
523 }
524 return ret;
525}
526
Michael Butler4b276a72020-08-06 23:22:35 -0700527nn::GeneralResult<OptionalTimeoutDuration> convert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800528 const nn::OptionalTimeoutDuration& optionalTimeoutDuration) {
529 OptionalTimeoutDuration ret;
530 if (optionalTimeoutDuration.has_value()) {
531 const auto count = optionalTimeoutDuration.value().count();
532 if (count < 0) {
Michael Butler4b276a72020-08-06 23:22:35 -0700533 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800534 << "Unable to convert OptionalTimeoutDuration because count is negative";
535 }
536 ret.nanoseconds(count);
537 }
538 return ret;
539}
540
Michael Butler4b276a72020-08-06 23:22:35 -0700541nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800542 switch (errorStatus) {
543 case nn::ErrorStatus::NONE:
544 case nn::ErrorStatus::DEVICE_UNAVAILABLE:
545 case nn::ErrorStatus::GENERAL_FAILURE:
546 case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
547 case nn::ErrorStatus::INVALID_ARGUMENT:
548 case nn::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
549 case nn::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
550 case nn::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
551 case nn::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
552 return static_cast<ErrorStatus>(errorStatus);
553 default:
554 return ErrorStatus::GENERAL_FAILURE;
555 }
556}
557
Michael Butler4b276a72020-08-06 23:22:35 -0700558nn::GeneralResult<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800559 return convertVec(bufferRoles);
560}
561
562} // namespace android::hardware::neuralnetworks::V1_3::utils