blob: 378719afc934df3a8fad97e7a6d710f33379ab87 [file] [log] [blame]
Michael Butlera685c3d2020-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.2/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/CommonUtils.h>
Michael Butler3670c382020-08-06 23:22:35 -070029#include <nnapi/hal/HandleError.h>
Michael Butlera685c3d2020-02-22 22:37:59 -080030
31#include <algorithm>
32#include <functional>
33#include <iterator>
34#include <memory>
35#include <type_traits>
36#include <utility>
37
38namespace {
39
40template <typename Type>
41constexpr std::underlying_type_t<Type> underlyingType(Type value) {
42 return static_cast<std::underlying_type_t<Type>>(value);
43}
44
45} // namespace
46
47namespace android::nn {
48namespace {
49
50constexpr bool validOperandType(OperandType operandType) {
51 switch (operandType) {
52 case OperandType::FLOAT32:
53 case OperandType::INT32:
54 case OperandType::UINT32:
55 case OperandType::TENSOR_FLOAT32:
56 case OperandType::TENSOR_INT32:
57 case OperandType::TENSOR_QUANT8_ASYMM:
58 case OperandType::BOOL:
59 case OperandType::TENSOR_QUANT16_SYMM:
60 case OperandType::TENSOR_FLOAT16:
61 case OperandType::TENSOR_BOOL8:
62 case OperandType::FLOAT16:
63 case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
64 case OperandType::TENSOR_QUANT16_ASYMM:
65 case OperandType::TENSOR_QUANT8_SYMM:
66 case OperandType::OEM:
67 case OperandType::TENSOR_OEM_BYTE:
68 return true;
69 default:
70 break;
71 }
72 return isExtension(operandType);
73}
74
75using hardware::hidl_handle;
76using hardware::hidl_vec;
77
78template <typename Input>
79using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
80
81template <typename Type>
Michael Butler3670c382020-08-06 23:22:35 -070082GeneralResult<std::vector<ConvertOutput<Type>>> convertVec(const hidl_vec<Type>& arguments) {
Michael Butlera685c3d2020-02-22 22:37:59 -080083 std::vector<ConvertOutput<Type>> canonical;
84 canonical.reserve(arguments.size());
85 for (const auto& argument : arguments) {
86 canonical.push_back(NN_TRY(nn::convert(argument)));
87 }
88 return canonical;
89}
90
91template <typename Type>
Michael Butler3670c382020-08-06 23:22:35 -070092GeneralResult<std::vector<ConvertOutput<Type>>> convert(const hidl_vec<Type>& arguments) {
Michael Butlera685c3d2020-02-22 22:37:59 -080093 return convertVec(arguments);
94}
95
96} // anonymous namespace
97
Michael Butler3670c382020-08-06 23:22:35 -070098GeneralResult<OperandType> convert(const hal::V1_2::OperandType& operandType) {
Michael Butlera685c3d2020-02-22 22:37:59 -080099 return static_cast<OperandType>(operandType);
100}
101
Michael Butler3670c382020-08-06 23:22:35 -0700102GeneralResult<OperationType> convert(const hal::V1_2::OperationType& operationType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800103 return static_cast<OperationType>(operationType);
104}
105
Michael Butler3670c382020-08-06 23:22:35 -0700106GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800107 return static_cast<DeviceType>(deviceType);
108}
109
Michael Butler3670c382020-08-06 23:22:35 -0700110GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800111 const bool validOperandTypes = std::all_of(
112 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
113 [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
114 const auto maybeType = convert(operandPerformance.type);
115 return !maybeType.has_value() ? false : validOperandType(maybeType.value());
116 });
117 if (!validOperandTypes) {
Michael Butler3670c382020-08-06 23:22:35 -0700118 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlera685c3d2020-02-22 22:37:59 -0800119 << "Invalid OperandType when converting OperandPerformance in Capabilities";
120 }
121
122 const auto relaxedFloat32toFloat16PerformanceScalar =
123 NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
124 const auto relaxedFloat32toFloat16PerformanceTensor =
125 NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
126 auto operandPerformance = NN_TRY(convert(capabilities.operandPerformance));
127
Michael Butler3670c382020-08-06 23:22:35 -0700128 auto table = NN_TRY(hal::utils::makeGeneralFailure(
129 Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
130 nn::ErrorStatus::GENERAL_FAILURE));
Michael Butlera685c3d2020-02-22 22:37:59 -0800131
132 return Capabilities{
133 .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
134 .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
135 .operandPerformance = std::move(table),
136 };
137}
138
Michael Butler3670c382020-08-06 23:22:35 -0700139GeneralResult<Capabilities::OperandPerformance> convert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800140 const hal::V1_2::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 Butler3670c382020-08-06 23:22:35 -0700147GeneralResult<Operation> convert(const hal::V1_2::Operation& operation) {
Michael Butlera685c3d2020-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 Butler3670c382020-08-06 23:22:35 -0700155GeneralResult<Operand::SymmPerChannelQuantParams> convert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800156 const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
157 return Operand::SymmPerChannelQuantParams{
158 .scales = symmPerChannelQuantParams.scales,
159 .channelDim = symmPerChannelQuantParams.channelDim,
160 };
161}
162
Michael Butler3670c382020-08-06 23:22:35 -0700163GeneralResult<Operand> convert(const hal::V1_2::Operand& operand) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800164 return Operand{
165 .type = NN_TRY(convert(operand.type)),
166 .dimensions = operand.dimensions,
167 .scale = operand.scale,
168 .zeroPoint = operand.zeroPoint,
169 .lifetime = NN_TRY(convert(operand.lifetime)),
170 .location = NN_TRY(convert(operand.location)),
171 .extraParams = NN_TRY(convert(operand.extraParams)),
172 };
173}
174
Michael Butler3670c382020-08-06 23:22:35 -0700175GeneralResult<Operand::ExtraParams> convert(const hal::V1_2::Operand::ExtraParams& extraParams) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800176 using Discriminator = hal::V1_2::Operand::ExtraParams::hidl_discriminator;
177 switch (extraParams.getDiscriminator()) {
178 case Discriminator::none:
179 return Operand::NoParams{};
180 case Discriminator::channelQuant:
181 return convert(extraParams.channelQuant());
182 case Discriminator::extension:
183 return extraParams.extension();
184 }
Michael Butler3670c382020-08-06 23:22:35 -0700185 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
186 << "Unrecognized Operand::ExtraParams discriminator: "
187 << underlyingType(extraParams.getDiscriminator());
Michael Butlera685c3d2020-02-22 22:37:59 -0800188}
189
Michael Butler3670c382020-08-06 23:22:35 -0700190GeneralResult<Model> convert(const hal::V1_2::Model& model) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800191 auto operations = NN_TRY(convert(model.operations));
192
193 // Verify number of consumers.
194 const auto numberOfConsumers =
195 hal::utils::countNumberOfConsumers(model.operands.size(), operations);
196 CHECK(model.operands.size() == numberOfConsumers.size());
197 for (size_t i = 0; i < model.operands.size(); ++i) {
198 if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler3670c382020-08-06 23:22:35 -0700199 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
200 << "Invalid numberOfConsumers for operand " << i << ", expected "
201 << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
Michael Butlera685c3d2020-02-22 22:37:59 -0800202 }
203 }
204
205 auto main = Model::Subgraph{
206 .operands = NN_TRY(convert(model.operands)),
207 .operations = std::move(operations),
208 .inputIndexes = model.inputIndexes,
209 .outputIndexes = model.outputIndexes,
210 };
211
212 return Model{
213 .main = std::move(main),
214 .operandValues = NN_TRY(convert(model.operandValues)),
215 .pools = NN_TRY(convert(model.pools)),
216 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
217 .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
218 };
219}
220
Michael Butler3670c382020-08-06 23:22:35 -0700221GeneralResult<Model::ExtensionNameAndPrefix> convert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800222 const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
223 return Model::ExtensionNameAndPrefix{
224 .name = extensionNameAndPrefix.name,
225 .prefix = extensionNameAndPrefix.prefix,
226 };
227}
228
Michael Butler3670c382020-08-06 23:22:35 -0700229GeneralResult<OutputShape> convert(const hal::V1_2::OutputShape& outputShape) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800230 return OutputShape{
231 .dimensions = outputShape.dimensions,
232 .isSufficient = outputShape.isSufficient,
233 };
234}
235
Michael Butler3670c382020-08-06 23:22:35 -0700236GeneralResult<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800237 return static_cast<MeasureTiming>(measureTiming);
238}
239
Michael Butler3670c382020-08-06 23:22:35 -0700240GeneralResult<Timing> convert(const hal::V1_2::Timing& timing) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800241 return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
242}
243
Michael Butler3670c382020-08-06 23:22:35 -0700244GeneralResult<Extension> convert(const hal::V1_2::Extension& extension) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800245 return Extension{
246 .name = extension.name,
247 .operandTypes = NN_TRY(convert(extension.operandTypes)),
248 };
249}
250
Michael Butler3670c382020-08-06 23:22:35 -0700251GeneralResult<Extension::OperandTypeInformation> convert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800252 const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation) {
253 return Extension::OperandTypeInformation{
254 .type = operandTypeInformation.type,
255 .isTensor = operandTypeInformation.isTensor,
256 .byteSize = operandTypeInformation.byteSize,
257 };
258}
259
Michael Butler3670c382020-08-06 23:22:35 -0700260GeneralResult<NativeHandle> convert(const hidl_handle& handle) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800261 auto* cloned = native_handle_clone(handle.getNativeHandle());
262 return ::android::NativeHandle::create(cloned, /*ownsHandle=*/true);
263}
264
Michael Butler3670c382020-08-06 23:22:35 -0700265GeneralResult<std::vector<Extension>> convert(const hidl_vec<hal::V1_2::Extension>& extensions) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800266 return convertVec(extensions);
267}
268
Michael Butler3670c382020-08-06 23:22:35 -0700269GeneralResult<std::vector<NativeHandle>> convert(const hidl_vec<hidl_handle>& handles) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800270 return convertVec(handles);
271}
272
Michael Butler3670c382020-08-06 23:22:35 -0700273GeneralResult<std::vector<OutputShape>> convert(
274 const hidl_vec<hal::V1_2::OutputShape>& outputShapes) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800275 return convertVec(outputShapes);
276}
277
278} // namespace android::nn
279
280namespace android::hardware::neuralnetworks::V1_2::utils {
281namespace {
282
283using utils::convert;
284
Michael Butler3670c382020-08-06 23:22:35 -0700285nn::GeneralResult<V1_0::OperandLifeTime> convert(const nn::Operand::LifeTime& lifetime) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800286 return V1_0::utils::convert(lifetime);
287}
288
Michael Butler3670c382020-08-06 23:22:35 -0700289nn::GeneralResult<V1_0::PerformanceInfo> convert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800290 const nn::Capabilities::PerformanceInfo& performanceInfo) {
291 return V1_0::utils::convert(performanceInfo);
292}
293
Michael Butler3670c382020-08-06 23:22:35 -0700294nn::GeneralResult<V1_0::DataLocation> convert(const nn::DataLocation& location) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800295 return V1_0::utils::convert(location);
296}
297
Michael Butler3670c382020-08-06 23:22:35 -0700298nn::GeneralResult<hidl_vec<uint8_t>> convert(const nn::Model::OperandValues& operandValues) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800299 return V1_0::utils::convert(operandValues);
300}
301
Michael Butler3670c382020-08-06 23:22:35 -0700302nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800303 return V1_0::utils::convert(memory);
304}
305
306template <typename Input>
307using ConvertOutput = std::decay_t<decltype(convert(std::declval<Input>()).value())>;
308
309template <typename Type>
Michael Butler3670c382020-08-06 23:22:35 -0700310nn::GeneralResult<hidl_vec<ConvertOutput<Type>>> convertVec(const std::vector<Type>& arguments) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800311 hidl_vec<ConvertOutput<Type>> halObject(arguments.size());
312 for (size_t i = 0; i < arguments.size(); ++i) {
313 halObject[i] = NN_TRY(convert(arguments[i]));
314 }
315 return halObject;
316}
317
318template <typename Type>
Michael Butler3670c382020-08-06 23:22:35 -0700319nn::GeneralResult<hidl_vec<ConvertOutput<Type>>> convert(const std::vector<Type>& arguments) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800320 return convertVec(arguments);
321}
322
Michael Butler3670c382020-08-06 23:22:35 -0700323nn::GeneralResult<Operand::ExtraParams> makeExtraParams(nn::Operand::NoParams /*noParams*/) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800324 return Operand::ExtraParams{};
325}
326
Michael Butler3670c382020-08-06 23:22:35 -0700327nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
Michael Butlera685c3d2020-02-22 22:37:59 -0800328 const nn::Operand::SymmPerChannelQuantParams& channelQuant) {
329 Operand::ExtraParams ret;
330 ret.channelQuant(NN_TRY(convert(channelQuant)));
331 return ret;
332}
333
Michael Butler3670c382020-08-06 23:22:35 -0700334nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
335 const nn::Operand::ExtensionParams& extension) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800336 Operand::ExtraParams ret;
337 ret.extension(extension);
338 return ret;
339}
340
341} // anonymous namespace
342
Michael Butler3670c382020-08-06 23:22:35 -0700343nn::GeneralResult<OperandType> convert(const nn::OperandType& operandType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800344 return static_cast<OperandType>(operandType);
345}
346
Michael Butler3670c382020-08-06 23:22:35 -0700347nn::GeneralResult<OperationType> convert(const nn::OperationType& operationType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800348 return static_cast<OperationType>(operationType);
349}
350
Michael Butler3670c382020-08-06 23:22:35 -0700351nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800352 switch (deviceType) {
353 case nn::DeviceType::UNKNOWN:
Michael Butler3670c382020-08-06 23:22:35 -0700354 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Invalid DeviceType UNKNOWN";
Michael Butlera685c3d2020-02-22 22:37:59 -0800355 case nn::DeviceType::OTHER:
356 case nn::DeviceType::CPU:
357 case nn::DeviceType::GPU:
358 case nn::DeviceType::ACCELERATOR:
359 return static_cast<DeviceType>(deviceType);
360 }
Michael Butler3670c382020-08-06 23:22:35 -0700361 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
362 << "Invalid DeviceType " << underlyingType(deviceType);
Michael Butlera685c3d2020-02-22 22:37:59 -0800363}
364
Michael Butler3670c382020-08-06 23:22:35 -0700365nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800366 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
367 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
368 std::copy_if(capabilities.operandPerformance.asVector().begin(),
369 capabilities.operandPerformance.asVector().end(),
370 std::back_inserter(operandPerformance),
371 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
372 return nn::validOperandType(operandPerformance.type);
373 });
374
375 return Capabilities{
376 .relaxedFloat32toFloat16PerformanceScalar =
377 NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
378 .relaxedFloat32toFloat16PerformanceTensor =
379 NN_TRY(convert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
380 .operandPerformance = NN_TRY(convert(operandPerformance)),
381 };
382}
383
Michael Butler3670c382020-08-06 23:22:35 -0700384nn::GeneralResult<Capabilities::OperandPerformance> convert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800385 const nn::Capabilities::OperandPerformance& operandPerformance) {
386 return Capabilities::OperandPerformance{
387 .type = NN_TRY(convert(operandPerformance.type)),
388 .info = NN_TRY(convert(operandPerformance.info)),
389 };
390}
391
Michael Butler3670c382020-08-06 23:22:35 -0700392nn::GeneralResult<Operation> convert(const nn::Operation& operation) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800393 return Operation{
394 .type = NN_TRY(convert(operation.type)),
395 .inputs = operation.inputs,
396 .outputs = operation.outputs,
397 };
398}
399
Michael Butler3670c382020-08-06 23:22:35 -0700400nn::GeneralResult<SymmPerChannelQuantParams> convert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800401 const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
402 return SymmPerChannelQuantParams{
403 .scales = symmPerChannelQuantParams.scales,
404 .channelDim = symmPerChannelQuantParams.channelDim,
405 };
406}
407
Michael Butler3670c382020-08-06 23:22:35 -0700408nn::GeneralResult<Operand> convert(const nn::Operand& operand) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800409 return Operand{
410 .type = NN_TRY(convert(operand.type)),
411 .dimensions = operand.dimensions,
412 .numberOfConsumers = 0,
413 .scale = operand.scale,
414 .zeroPoint = operand.zeroPoint,
415 .lifetime = NN_TRY(convert(operand.lifetime)),
416 .location = NN_TRY(convert(operand.location)),
417 .extraParams = NN_TRY(convert(operand.extraParams)),
418 };
419}
420
Michael Butler3670c382020-08-06 23:22:35 -0700421nn::GeneralResult<Operand::ExtraParams> convert(const nn::Operand::ExtraParams& extraParams) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800422 return std::visit([](const auto& x) { return makeExtraParams(x); }, extraParams);
423}
424
Michael Butler3670c382020-08-06 23:22:35 -0700425nn::GeneralResult<Model> convert(const nn::Model& model) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800426 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler3670c382020-08-06 23:22:35 -0700427 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
428 << "Model cannot be converted because it contains pointer-based memory";
Michael Butlera685c3d2020-02-22 22:37:59 -0800429 }
430
431 auto operands = NN_TRY(convert(model.main.operands));
432
433 // Update number of consumers.
434 const auto numberOfConsumers =
435 hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
436 CHECK(operands.size() == numberOfConsumers.size());
437 for (size_t i = 0; i < operands.size(); ++i) {
438 operands[i].numberOfConsumers = numberOfConsumers[i];
439 }
440
441 return Model{
442 .operands = std::move(operands),
443 .operations = NN_TRY(convert(model.main.operations)),
444 .inputIndexes = model.main.inputIndexes,
445 .outputIndexes = model.main.outputIndexes,
446 .operandValues = NN_TRY(convert(model.operandValues)),
447 .pools = NN_TRY(convert(model.pools)),
448 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
449 .extensionNameToPrefix = NN_TRY(convert(model.extensionNameToPrefix)),
450 };
451}
452
Michael Butler3670c382020-08-06 23:22:35 -0700453nn::GeneralResult<Model::ExtensionNameAndPrefix> convert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800454 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
455 return Model::ExtensionNameAndPrefix{
456 .name = extensionNameAndPrefix.name,
457 .prefix = extensionNameAndPrefix.prefix,
458 };
459}
460
Michael Butler3670c382020-08-06 23:22:35 -0700461nn::GeneralResult<OutputShape> convert(const nn::OutputShape& outputShape) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800462 return OutputShape{.dimensions = outputShape.dimensions,
463 .isSufficient = outputShape.isSufficient};
464}
465
Michael Butler3670c382020-08-06 23:22:35 -0700466nn::GeneralResult<MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800467 return static_cast<MeasureTiming>(measureTiming);
468}
469
Michael Butler3670c382020-08-06 23:22:35 -0700470nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800471 return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
472}
473
Michael Butler3670c382020-08-06 23:22:35 -0700474nn::GeneralResult<Extension> convert(const nn::Extension& extension) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800475 return Extension{
476 .name = extension.name,
477 .operandTypes = NN_TRY(convert(extension.operandTypes)),
478 };
479}
480
Michael Butler3670c382020-08-06 23:22:35 -0700481nn::GeneralResult<Extension::OperandTypeInformation> convert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800482 const nn::Extension::OperandTypeInformation& operandTypeInformation) {
483 return Extension::OperandTypeInformation{
484 .type = operandTypeInformation.type,
485 .isTensor = operandTypeInformation.isTensor,
486 .byteSize = operandTypeInformation.byteSize,
487 };
488}
489
Michael Butler3670c382020-08-06 23:22:35 -0700490nn::GeneralResult<hidl_handle> convert(const nn::NativeHandle& handle) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800491 const auto hidlHandle = hidl_handle(handle->handle());
492 // Copy memory to force the native_handle_t to be copied.
493 auto copiedHandle = hidlHandle;
494 return copiedHandle;
495}
496
Michael Butler3670c382020-08-06 23:22:35 -0700497nn::GeneralResult<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800498 return convertVec(extensions);
499}
500
Michael Butler3670c382020-08-06 23:22:35 -0700501nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::NativeHandle>& handles) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800502 return convertVec(handles);
503}
504
Michael Butler3670c382020-08-06 23:22:35 -0700505nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800506 return convertVec(outputShapes);
507}
508
509} // namespace android::hardware::neuralnetworks::V1_2::utils