blob: eb28db7587e2c928c0312a18f6c1c08118c40845 [file] [log] [blame]
Lev Proleev6b6dfcd2020-11-11 18:28:50 +00001/*
2 * Copyright (C) 2021 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
Michael Butlerf03ebd92021-03-25 15:27:38 -070019#include <aidl/android/hardware/common/Ashmem.h>
20#include <aidl/android/hardware/common/MappableFile.h>
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000021#include <aidl/android/hardware/common/NativeHandle.h>
Michael Butlerf03ebd92021-03-25 15:27:38 -070022#include <aidl/android/hardware/graphics/common/HardwareBuffer.h>
23#include <aidlcommonsupport/NativeHandle.h>
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000024#include <android-base/logging.h>
Michael Butlerf03ebd92021-03-25 15:27:38 -070025#include <android-base/mapped_file.h>
Lev Proleev900c28a2021-01-26 19:40:20 +000026#include <android-base/unique_fd.h>
27#include <android/binder_auto_utils.h>
Michael Butlerab2f4822021-02-08 00:05:07 -080028#include <cutils/native_handle.h>
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000029#include <nnapi/OperandTypes.h>
30#include <nnapi/OperationTypes.h>
31#include <nnapi/Result.h>
32#include <nnapi/SharedMemory.h>
33#include <nnapi/TypeUtils.h>
34#include <nnapi/Types.h>
35#include <nnapi/Validation.h>
36#include <nnapi/hal/CommonUtils.h>
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000037
38#include <algorithm>
39#include <chrono>
40#include <functional>
41#include <iterator>
42#include <limits>
43#include <type_traits>
44#include <utility>
45
Michael Butler388bceb2021-02-03 15:15:43 -080046#include "Utils.h"
47
Ray Hernandez338d6f82021-08-11 21:29:20 +000048#ifdef __ANDROID__
49#include <android/hardware_buffer.h>
50#include <vndk/hardware_buffer.h>
51#endif // __ANDROID__
52
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000053#define VERIFY_NON_NEGATIVE(value) \
54 while (UNLIKELY(value < 0)) return NN_ERROR()
55
Lev Proleev900c28a2021-01-26 19:40:20 +000056#define VERIFY_LE_INT32_MAX(value) \
57 while (UNLIKELY(value > std::numeric_limits<int32_t>::max())) return NN_ERROR()
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000058
Lev Proleev900c28a2021-01-26 19:40:20 +000059namespace {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000060template <typename Type>
61constexpr std::underlying_type_t<Type> underlyingType(Type value) {
62 return static_cast<std::underlying_type_t<Type>>(value);
63}
64
Lev Proleev900c28a2021-01-26 19:40:20 +000065constexpr int64_t kNoTiming = -1;
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000066
67} // namespace
68
69namespace android::nn {
70namespace {
71
Michael Butlerfadeb8a2021-02-07 00:11:13 -080072using ::aidl::android::hardware::common::NativeHandle;
73
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000074template <typename Input>
75using UnvalidatedConvertOutput =
76 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
77
78template <typename Type>
79GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
80 const std::vector<Type>& arguments) {
81 std::vector<UnvalidatedConvertOutput<Type>> canonical;
82 canonical.reserve(arguments.size());
83 for (const auto& argument : arguments) {
84 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
85 }
86 return canonical;
87}
88
89template <typename Type>
90GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
91 const std::vector<Type>& arguments) {
92 return unvalidatedConvertVec(arguments);
93}
94
95template <typename Type>
96GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& halObject) {
97 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
Michael Butler388bceb2021-02-03 15:15:43 -080098 NN_TRY(aidl_hal::utils::compliantVersion(canonical));
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000099 return canonical;
100}
101
102template <typename Type>
103GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
104 const std::vector<Type>& arguments) {
105 std::vector<UnvalidatedConvertOutput<Type>> canonical;
106 canonical.reserve(arguments.size());
107 for (const auto& argument : arguments) {
108 canonical.push_back(NN_TRY(validatedConvert(argument)));
109 }
110 return canonical;
111}
112
Michael Butlerab2f4822021-02-08 00:05:07 -0800113struct NativeHandleDeleter {
114 void operator()(native_handle_t* handle) const {
115 if (handle) {
116 native_handle_close(handle);
117 native_handle_delete(handle);
118 }
119 }
120};
121
122using UniqueNativeHandle = std::unique_ptr<native_handle_t, NativeHandleDeleter>;
123
Ray Hernandez338d6f82021-08-11 21:29:20 +0000124#ifdef __ANDROID__
Michael Butlerf03ebd92021-03-25 15:27:38 -0700125GeneralResult<UniqueNativeHandle> nativeHandleFromAidlHandle(const NativeHandle& handle) {
126 auto nativeHandle = UniqueNativeHandle(dupFromAidl(handle));
127 if (nativeHandle.get() == nullptr) {
128 return NN_ERROR() << "android::dupFromAidl failed to convert the common::NativeHandle to a "
129 "native_handle_t";
Michael Butlerab2f4822021-02-08 00:05:07 -0800130 }
Michael Butlerf03ebd92021-03-25 15:27:38 -0700131 if (!std::all_of(nativeHandle->data + 0, nativeHandle->data + nativeHandle->numFds,
132 [](int fd) { return fd >= 0; })) {
133 return NN_ERROR() << "android::dupFromAidl returned an invalid native_handle_t";
Michael Butlerab2f4822021-02-08 00:05:07 -0800134 }
Michael Butlerf03ebd92021-03-25 15:27:38 -0700135 return nativeHandle;
Michael Butlerab2f4822021-02-08 00:05:07 -0800136}
Ray Hernandez338d6f82021-08-11 21:29:20 +0000137#endif // __ANDROID__
Michael Butlerab2f4822021-02-08 00:05:07 -0800138
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000139} // anonymous namespace
140
141GeneralResult<OperandType> unvalidatedConvert(const aidl_hal::OperandType& operandType) {
142 VERIFY_NON_NEGATIVE(underlyingType(operandType)) << "Negative operand types are not allowed.";
Michael Butler388bceb2021-02-03 15:15:43 -0800143 const auto canonical = static_cast<OperandType>(operandType);
144 if (canonical == OperandType::OEM || canonical == OperandType::TENSOR_OEM_BYTE) {
145 return NN_ERROR() << "Unable to convert invalid OperandType " << canonical;
146 }
147 return canonical;
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000148}
149
150GeneralResult<OperationType> unvalidatedConvert(const aidl_hal::OperationType& operationType) {
151 VERIFY_NON_NEGATIVE(underlyingType(operationType))
152 << "Negative operation types are not allowed.";
Michael Butler388bceb2021-02-03 15:15:43 -0800153 const auto canonical = static_cast<OperationType>(operationType);
154 if (canonical == OperationType::OEM_OPERATION) {
155 return NN_ERROR() << "Unable to convert invalid OperationType OEM_OPERATION";
156 }
157 return canonical;
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000158}
159
160GeneralResult<DeviceType> unvalidatedConvert(const aidl_hal::DeviceType& deviceType) {
161 return static_cast<DeviceType>(deviceType);
162}
163
164GeneralResult<Priority> unvalidatedConvert(const aidl_hal::Priority& priority) {
165 return static_cast<Priority>(priority);
166}
167
168GeneralResult<Capabilities> unvalidatedConvert(const aidl_hal::Capabilities& capabilities) {
169 const bool validOperandTypes = std::all_of(
170 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
171 [](const aidl_hal::OperandPerformance& operandPerformance) {
Michael Butler388bceb2021-02-03 15:15:43 -0800172 return validatedConvert(operandPerformance.type).has_value();
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000173 });
174 if (!validOperandTypes) {
175 return NN_ERROR() << "Invalid OperandType when unvalidatedConverting OperandPerformance in "
176 "Capabilities";
177 }
178
179 auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
Michael Butlerff9a5a52021-10-15 16:23:20 -0700180 auto table =
181 NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000182
183 return Capabilities{
184 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
185 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
186 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
187 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
188 .operandPerformance = std::move(table),
189 .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
190 .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
191 };
192}
193
194GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
195 const aidl_hal::OperandPerformance& operandPerformance) {
196 return Capabilities::OperandPerformance{
197 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
198 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
199 };
200}
201
202GeneralResult<Capabilities::PerformanceInfo> unvalidatedConvert(
203 const aidl_hal::PerformanceInfo& performanceInfo) {
204 return Capabilities::PerformanceInfo{
205 .execTime = performanceInfo.execTime,
206 .powerUsage = performanceInfo.powerUsage,
207 };
208}
209
210GeneralResult<DataLocation> unvalidatedConvert(const aidl_hal::DataLocation& location) {
211 VERIFY_NON_NEGATIVE(location.poolIndex) << "DataLocation: pool index must not be negative";
212 VERIFY_NON_NEGATIVE(location.offset) << "DataLocation: offset must not be negative";
213 VERIFY_NON_NEGATIVE(location.length) << "DataLocation: length must not be negative";
Xusong Wang5e36ca02021-02-16 10:40:32 -0800214 VERIFY_NON_NEGATIVE(location.padding) << "DataLocation: padding must not be negative";
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000215 if (location.offset > std::numeric_limits<uint32_t>::max()) {
216 return NN_ERROR() << "DataLocation: offset must be <= std::numeric_limits<uint32_t>::max()";
217 }
218 if (location.length > std::numeric_limits<uint32_t>::max()) {
219 return NN_ERROR() << "DataLocation: length must be <= std::numeric_limits<uint32_t>::max()";
220 }
Xusong Wang5e36ca02021-02-16 10:40:32 -0800221 if (location.padding > std::numeric_limits<uint32_t>::max()) {
222 return NN_ERROR()
223 << "DataLocation: padding must be <= std::numeric_limits<uint32_t>::max()";
224 }
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000225 return DataLocation{
226 .poolIndex = static_cast<uint32_t>(location.poolIndex),
227 .offset = static_cast<uint32_t>(location.offset),
228 .length = static_cast<uint32_t>(location.length),
Xusong Wang5e36ca02021-02-16 10:40:32 -0800229 .padding = static_cast<uint32_t>(location.padding),
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000230 };
231}
232
233GeneralResult<Operation> unvalidatedConvert(const aidl_hal::Operation& operation) {
234 return Operation{
235 .type = NN_TRY(unvalidatedConvert(operation.type)),
236 .inputs = NN_TRY(toUnsigned(operation.inputs)),
237 .outputs = NN_TRY(toUnsigned(operation.outputs)),
238 };
239}
240
241GeneralResult<Operand::LifeTime> unvalidatedConvert(
242 const aidl_hal::OperandLifeTime& operandLifeTime) {
243 return static_cast<Operand::LifeTime>(operandLifeTime);
244}
245
246GeneralResult<Operand> unvalidatedConvert(const aidl_hal::Operand& operand) {
247 return Operand{
248 .type = NN_TRY(unvalidatedConvert(operand.type)),
249 .dimensions = NN_TRY(toUnsigned(operand.dimensions)),
250 .scale = operand.scale,
251 .zeroPoint = operand.zeroPoint,
252 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
253 .location = NN_TRY(unvalidatedConvert(operand.location)),
254 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
255 };
256}
257
258GeneralResult<Operand::ExtraParams> unvalidatedConvert(
259 const std::optional<aidl_hal::OperandExtraParams>& optionalExtraParams) {
260 if (!optionalExtraParams.has_value()) {
261 return Operand::NoParams{};
262 }
263 const auto& extraParams = optionalExtraParams.value();
264 using Tag = aidl_hal::OperandExtraParams::Tag;
265 switch (extraParams.getTag()) {
266 case Tag::channelQuant:
267 return unvalidatedConvert(extraParams.get<Tag::channelQuant>());
268 case Tag::extension:
269 return extraParams.get<Tag::extension>();
270 }
271 return NN_ERROR() << "Unrecognized Operand::ExtraParams tag: "
272 << underlyingType(extraParams.getTag());
273}
274
275GeneralResult<Operand::SymmPerChannelQuantParams> unvalidatedConvert(
276 const aidl_hal::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
277 VERIFY_NON_NEGATIVE(symmPerChannelQuantParams.channelDim)
278 << "Per-channel quantization channel dimension must not be negative.";
279 return Operand::SymmPerChannelQuantParams{
280 .scales = symmPerChannelQuantParams.scales,
281 .channelDim = static_cast<uint32_t>(symmPerChannelQuantParams.channelDim),
282 };
283}
284
285GeneralResult<Model> unvalidatedConvert(const aidl_hal::Model& model) {
286 return Model{
287 .main = NN_TRY(unvalidatedConvert(model.main)),
288 .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
289 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
290 .pools = NN_TRY(unvalidatedConvert(model.pools)),
291 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
292 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
293 };
294}
295
296GeneralResult<Model::Subgraph> unvalidatedConvert(const aidl_hal::Subgraph& subgraph) {
297 return Model::Subgraph{
298 .operands = NN_TRY(unvalidatedConvert(subgraph.operands)),
299 .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
300 .inputIndexes = NN_TRY(toUnsigned(subgraph.inputIndexes)),
301 .outputIndexes = NN_TRY(toUnsigned(subgraph.outputIndexes)),
302 };
303}
304
Miao Wang0e671f32021-10-26 20:03:05 +0000305GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000306 const aidl_hal::ExtensionNameAndPrefix& extensionNameAndPrefix) {
Miao Wang0e671f32021-10-26 20:03:05 +0000307 return ExtensionNameAndPrefix{
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000308 .name = extensionNameAndPrefix.name,
309 .prefix = extensionNameAndPrefix.prefix,
310 };
311}
312
313GeneralResult<Extension> unvalidatedConvert(const aidl_hal::Extension& extension) {
314 return Extension{
315 .name = extension.name,
316 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
317 };
318}
319
320GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
321 const aidl_hal::ExtensionOperandTypeInformation& operandTypeInformation) {
322 VERIFY_NON_NEGATIVE(operandTypeInformation.byteSize)
323 << "Extension operand type byte size must not be negative";
324 return Extension::OperandTypeInformation{
325 .type = operandTypeInformation.type,
326 .isTensor = operandTypeInformation.isTensor,
327 .byteSize = static_cast<uint32_t>(operandTypeInformation.byteSize),
328 };
329}
330
331GeneralResult<OutputShape> unvalidatedConvert(const aidl_hal::OutputShape& outputShape) {
332 return OutputShape{
333 .dimensions = NN_TRY(toUnsigned(outputShape.dimensions)),
334 .isSufficient = outputShape.isSufficient,
335 };
336}
337
338GeneralResult<MeasureTiming> unvalidatedConvert(bool measureTiming) {
339 return measureTiming ? MeasureTiming::YES : MeasureTiming::NO;
340}
341
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800342GeneralResult<SharedMemory> unvalidatedConvert(const aidl_hal::Memory& memory) {
Michael Butlerf03ebd92021-03-25 15:27:38 -0700343 using Tag = aidl_hal::Memory::Tag;
344 switch (memory.getTag()) {
345 case Tag::ashmem: {
346 const auto& ashmem = memory.get<Tag::ashmem>();
347 VERIFY_NON_NEGATIVE(ashmem.size) << "Memory size must not be negative";
348 if (ashmem.size > std::numeric_limits<size_t>::max()) {
349 return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
350 }
Michael Butlerab2f4822021-02-08 00:05:07 -0800351
Michael Butlerf03ebd92021-03-25 15:27:38 -0700352 auto handle = Memory::Ashmem{
353 .fd = NN_TRY(dupFd(ashmem.fd.get())),
354 .size = static_cast<size_t>(ashmem.size),
355 };
356 return std::make_shared<const Memory>(Memory{.handle = std::move(handle)});
357 }
358 case Tag::mappableFile: {
359 const auto& mappableFile = memory.get<Tag::mappableFile>();
360 VERIFY_NON_NEGATIVE(mappableFile.length) << "Memory size must not be negative";
361 VERIFY_NON_NEGATIVE(mappableFile.offset) << "Memory offset must not be negative";
362 if (mappableFile.length > std::numeric_limits<size_t>::max()) {
363 return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
364 }
365 if (mappableFile.offset > std::numeric_limits<size_t>::max()) {
366 return NN_ERROR() << "Memory: offset must be <= std::numeric_limits<size_t>::max()";
367 }
Michael Butlerab2f4822021-02-08 00:05:07 -0800368
Michael Butlerf03ebd92021-03-25 15:27:38 -0700369 const size_t size = static_cast<size_t>(mappableFile.length);
370 const int prot = mappableFile.prot;
371 const int fd = mappableFile.fd.get();
372 const size_t offset = static_cast<size_t>(mappableFile.offset);
Michael Butlerab2f4822021-02-08 00:05:07 -0800373
Michael Butlerf03ebd92021-03-25 15:27:38 -0700374 return createSharedMemoryFromFd(size, prot, fd, offset);
375 }
376 case Tag::hardwareBuffer: {
Ray Hernandez338d6f82021-08-11 21:29:20 +0000377#ifdef __ANDROID__
Michael Butlerf03ebd92021-03-25 15:27:38 -0700378 const auto& hardwareBuffer = memory.get<Tag::hardwareBuffer>();
Michael Butlerab2f4822021-02-08 00:05:07 -0800379
Michael Butlerf03ebd92021-03-25 15:27:38 -0700380 const UniqueNativeHandle handle =
381 NN_TRY(nativeHandleFromAidlHandle(hardwareBuffer.handle));
382 const native_handle_t* nativeHandle = handle.get();
383
384 const AHardwareBuffer_Desc desc{
385 .width = static_cast<uint32_t>(hardwareBuffer.description.width),
386 .height = static_cast<uint32_t>(hardwareBuffer.description.height),
387 .layers = static_cast<uint32_t>(hardwareBuffer.description.layers),
388 .format = static_cast<uint32_t>(hardwareBuffer.description.format),
389 .usage = static_cast<uint64_t>(hardwareBuffer.description.usage),
390 .stride = static_cast<uint32_t>(hardwareBuffer.description.stride),
391 };
392 AHardwareBuffer* ahwb = nullptr;
393 const status_t status = AHardwareBuffer_createFromHandle(
394 &desc, nativeHandle, AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, &ahwb);
395 if (status != NO_ERROR) {
396 return NN_ERROR() << "createFromHandle failed";
397 }
398
399 return createSharedMemoryFromAHWB(ahwb, /*takeOwnership=*/true);
Ray Hernandez338d6f82021-08-11 21:29:20 +0000400#else // __ANDROID__
401 LOG(FATAL) << "GeneralResult<SharedMemory> unvalidatedConvert(const aidl_hal::Memory& "
402 "memory): Not Available on Host Build";
403 return NN_ERROR() << "createFromHandle failed";
404#endif // __ANDROID__
Michael Butlerab2f4822021-02-08 00:05:07 -0800405 }
406 }
Michael Butlerf03ebd92021-03-25 15:27:38 -0700407 return NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag();
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000408}
409
Lev Proleev900c28a2021-01-26 19:40:20 +0000410GeneralResult<Timing> unvalidatedConvert(const aidl_hal::Timing& timing) {
Lev Proleev8df7d6e2021-04-14 20:54:27 +0100411 if (timing.timeInDriverNs < -1) {
412 return NN_ERROR() << "Timing: timeInDriverNs must not be less than -1";
Lev Proleev900c28a2021-01-26 19:40:20 +0000413 }
Lev Proleev8df7d6e2021-04-14 20:54:27 +0100414 if (timing.timeOnDeviceNs < -1) {
415 return NN_ERROR() << "Timing: timeOnDeviceNs must not be less than -1";
Lev Proleev900c28a2021-01-26 19:40:20 +0000416 }
417 constexpr auto convertTiming = [](int64_t halTiming) -> OptionalDuration {
418 if (halTiming == kNoTiming) {
419 return {};
420 }
421 return nn::Duration(static_cast<uint64_t>(halTiming));
422 };
Lev Proleev8df7d6e2021-04-14 20:54:27 +0100423 return Timing{.timeOnDevice = convertTiming(timing.timeOnDeviceNs),
424 .timeInDriver = convertTiming(timing.timeInDriverNs)};
Lev Proleev900c28a2021-01-26 19:40:20 +0000425}
426
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000427GeneralResult<Model::OperandValues> unvalidatedConvert(const std::vector<uint8_t>& operandValues) {
428 return Model::OperandValues(operandValues.data(), operandValues.size());
429}
430
431GeneralResult<BufferDesc> unvalidatedConvert(const aidl_hal::BufferDesc& bufferDesc) {
432 return BufferDesc{.dimensions = NN_TRY(toUnsigned(bufferDesc.dimensions))};
433}
434
435GeneralResult<BufferRole> unvalidatedConvert(const aidl_hal::BufferRole& bufferRole) {
436 VERIFY_NON_NEGATIVE(bufferRole.modelIndex) << "BufferRole: modelIndex must not be negative";
437 VERIFY_NON_NEGATIVE(bufferRole.ioIndex) << "BufferRole: ioIndex must not be negative";
438 return BufferRole{
439 .modelIndex = static_cast<uint32_t>(bufferRole.modelIndex),
440 .ioIndex = static_cast<uint32_t>(bufferRole.ioIndex),
Xusong Wang3633d072021-03-19 13:58:24 -0700441 .probability = bufferRole.probability,
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000442 };
443}
444
445GeneralResult<Request> unvalidatedConvert(const aidl_hal::Request& request) {
446 return Request{
447 .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
448 .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
449 .pools = NN_TRY(unvalidatedConvert(request.pools)),
450 };
451}
452
453GeneralResult<Request::Argument> unvalidatedConvert(const aidl_hal::RequestArgument& argument) {
454 const auto lifetime = argument.hasNoValue ? Request::Argument::LifeTime::NO_VALUE
455 : Request::Argument::LifeTime::POOL;
456 return Request::Argument{
457 .lifetime = lifetime,
458 .location = NN_TRY(unvalidatedConvert(argument.location)),
459 .dimensions = NN_TRY(toUnsigned(argument.dimensions)),
460 };
461}
462
463GeneralResult<Request::MemoryPool> unvalidatedConvert(
464 const aidl_hal::RequestMemoryPool& memoryPool) {
465 using Tag = aidl_hal::RequestMemoryPool::Tag;
466 switch (memoryPool.getTag()) {
467 case Tag::pool:
468 return unvalidatedConvert(memoryPool.get<Tag::pool>());
469 case Tag::token: {
470 const auto token = memoryPool.get<Tag::token>();
471 VERIFY_NON_NEGATIVE(token) << "Memory pool token must not be negative";
472 return static_cast<Request::MemoryDomainToken>(token);
473 }
474 }
475 return NN_ERROR() << "Invalid Request::MemoryPool tag " << underlyingType(memoryPool.getTag());
476}
477
478GeneralResult<ErrorStatus> unvalidatedConvert(const aidl_hal::ErrorStatus& status) {
479 switch (status) {
480 case aidl_hal::ErrorStatus::NONE:
481 case aidl_hal::ErrorStatus::DEVICE_UNAVAILABLE:
482 case aidl_hal::ErrorStatus::GENERAL_FAILURE:
483 case aidl_hal::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
484 case aidl_hal::ErrorStatus::INVALID_ARGUMENT:
485 case aidl_hal::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
486 case aidl_hal::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
487 case aidl_hal::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
488 case aidl_hal::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
489 return static_cast<ErrorStatus>(status);
490 }
491 return NN_ERROR() << "Invalid ErrorStatus " << underlyingType(status);
492}
493
494GeneralResult<ExecutionPreference> unvalidatedConvert(
495 const aidl_hal::ExecutionPreference& executionPreference) {
496 return static_cast<ExecutionPreference>(executionPreference);
497}
498
Michael Butler388bceb2021-02-03 15:15:43 -0800499GeneralResult<std::vector<Operation>> unvalidatedConvert(
500 const std::vector<aidl_hal::Operation>& operations) {
501 return unvalidatedConvertVec(operations);
502}
503
Michael Butlere52a77e2021-06-07 13:10:58 -0700504GeneralResult<SharedHandle> unvalidatedConvert(const ndk::ScopedFileDescriptor& handle) {
505 auto duplicatedFd = NN_TRY(dupFd(handle.get()));
506 return std::make_shared<const Handle>(std::move(duplicatedFd));
Lev Proleev900c28a2021-01-26 19:40:20 +0000507}
508
Miao Wang0e671f32021-10-26 20:03:05 +0000509#ifdef NN_AIDL_V4_OR_ABOVE
510GeneralResult<TokenValuePair> unvalidatedConvert(const aidl_hal::TokenValuePair& tokenValuePair) {
511 return TokenValuePair{.token = tokenValuePair.token, .value = tokenValuePair.value};
512}
513#endif // NN_AIDL_V4_OR_ABOVE
514
Lev Proleev900c28a2021-01-26 19:40:20 +0000515GeneralResult<Capabilities> convert(const aidl_hal::Capabilities& capabilities) {
516 return validatedConvert(capabilities);
517}
518
519GeneralResult<DeviceType> convert(const aidl_hal::DeviceType& deviceType) {
520 return validatedConvert(deviceType);
521}
522
523GeneralResult<ErrorStatus> convert(const aidl_hal::ErrorStatus& errorStatus) {
524 return validatedConvert(errorStatus);
525}
526
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000527GeneralResult<ExecutionPreference> convert(
528 const aidl_hal::ExecutionPreference& executionPreference) {
529 return validatedConvert(executionPreference);
530}
531
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800532GeneralResult<SharedMemory> convert(const aidl_hal::Memory& operand) {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000533 return validatedConvert(operand);
534}
535
536GeneralResult<Model> convert(const aidl_hal::Model& model) {
537 return validatedConvert(model);
538}
539
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000540GeneralResult<OperandType> convert(const aidl_hal::OperandType& operandType) {
Michael Butler388bceb2021-02-03 15:15:43 -0800541 return validatedConvert(operandType);
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000542}
543
544GeneralResult<Priority> convert(const aidl_hal::Priority& priority) {
545 return validatedConvert(priority);
546}
547
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000548GeneralResult<Request> convert(const aidl_hal::Request& request) {
549 return validatedConvert(request);
550}
551
Lev Proleev900c28a2021-01-26 19:40:20 +0000552GeneralResult<Timing> convert(const aidl_hal::Timing& timing) {
553 return validatedConvert(timing);
554}
555
Michael Butlere52a77e2021-06-07 13:10:58 -0700556GeneralResult<SharedHandle> convert(const ndk::ScopedFileDescriptor& handle) {
557 return validatedConvert(handle);
Lev Proleev900c28a2021-01-26 19:40:20 +0000558}
559
Michael Butler53455632021-10-25 11:20:33 -0700560GeneralResult<BufferDesc> convert(const aidl_hal::BufferDesc& bufferDesc) {
561 return validatedConvert(bufferDesc);
562}
563
Lev Proleev900c28a2021-01-26 19:40:20 +0000564GeneralResult<std::vector<Extension>> convert(const std::vector<aidl_hal::Extension>& extension) {
565 return validatedConvert(extension);
566}
567
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800568GeneralResult<std::vector<SharedMemory>> convert(const std::vector<aidl_hal::Memory>& memories) {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000569 return validatedConvert(memories);
570}
Miao Wang0e671f32021-10-26 20:03:05 +0000571GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
572 const std::vector<aidl_hal::ExtensionNameAndPrefix>& extensionNameAndPrefix) {
573 return unvalidatedConvert(extensionNameAndPrefix);
574}
575
576#ifdef NN_AIDL_V4_OR_ABOVE
577GeneralResult<std::vector<TokenValuePair>> convert(
578 const std::vector<aidl_hal::TokenValuePair>& metaData) {
579 return validatedConvert(metaData);
580}
581#endif // NN_AIDL_V4_OR_ABOVE
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000582
Lev Proleev900c28a2021-01-26 19:40:20 +0000583GeneralResult<std::vector<OutputShape>> convert(
584 const std::vector<aidl_hal::OutputShape>& outputShapes) {
585 return validatedConvert(outputShapes);
586}
587
Michael Butler53455632021-10-25 11:20:33 -0700588GeneralResult<std::vector<SharedHandle>> convert(
589 const std::vector<ndk::ScopedFileDescriptor>& handles) {
590 return validatedConvert(handles);
591}
592
593GeneralResult<std::vector<BufferRole>> convert(const std::vector<aidl_hal::BufferRole>& roles) {
594 return validatedConvert(roles);
595}
596
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000597GeneralResult<std::vector<uint32_t>> toUnsigned(const std::vector<int32_t>& vec) {
598 if (!std::all_of(vec.begin(), vec.end(), [](int32_t v) { return v >= 0; })) {
599 return NN_ERROR() << "Negative value passed to conversion from signed to unsigned";
600 }
601 return std::vector<uint32_t>(vec.begin(), vec.end());
602}
603
604} // namespace android::nn
605
606namespace aidl::android::hardware::neuralnetworks::utils {
607namespace {
608
Michael Butler53455632021-10-25 11:20:33 -0700609using utils::unvalidatedConvert;
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000610
Lev Proleev900c28a2021-01-26 19:40:20 +0000611// Helper template for std::visit
612template <class... Ts>
613struct overloaded : Ts... {
614 using Ts::operator()...;
615};
616template <class... Ts>
617overloaded(Ts...)->overloaded<Ts...>;
618
Ray Hernandez338d6f82021-08-11 21:29:20 +0000619#ifdef __ANDROID__
Michael Butlerf03ebd92021-03-25 15:27:38 -0700620nn::GeneralResult<common::NativeHandle> aidlHandleFromNativeHandle(
621 const native_handle_t& nativeHandle) {
622 auto handle = ::android::dupToAidl(&nativeHandle);
623 if (!std::all_of(handle.fds.begin(), handle.fds.end(),
624 [](const ndk::ScopedFileDescriptor& fd) { return fd.get() >= 0; })) {
625 return NN_ERROR() << "android::dupToAidl returned an invalid common::NativeHandle";
626 }
627 return handle;
628}
Ray Hernandez338d6f82021-08-11 21:29:20 +0000629#endif // __ANDROID__
Michael Butlerab2f4822021-02-08 00:05:07 -0800630
Michael Butlerf03ebd92021-03-25 15:27:38 -0700631nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Ashmem& memory) {
632 if constexpr (std::numeric_limits<size_t>::max() > std::numeric_limits<int64_t>::max()) {
633 if (memory.size > std::numeric_limits<int64_t>::max()) {
634 return (
635 NN_ERROR()
636 << "Memory::Ashmem: size must be <= std::numeric_limits<int64_t>::max()")
637 .
638 operator nn::GeneralResult<Memory>();
639 }
Michael Butlerab2f4822021-02-08 00:05:07 -0800640 }
641
Michael Butlerf03ebd92021-03-25 15:27:38 -0700642 auto fd = NN_TRY(nn::dupFd(memory.fd));
643 auto handle = common::Ashmem{
644 .fd = ndk::ScopedFileDescriptor(fd.release()),
645 .size = static_cast<int64_t>(memory.size),
646 };
647 return Memory::make<Memory::Tag::ashmem>(std::move(handle));
648}
Michael Butlerab2f4822021-02-08 00:05:07 -0800649
Michael Butlerf03ebd92021-03-25 15:27:38 -0700650nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Fd& memory) {
651 if constexpr (std::numeric_limits<size_t>::max() > std::numeric_limits<int64_t>::max()) {
652 if (memory.size > std::numeric_limits<int64_t>::max()) {
653 return (NN_ERROR() << "Memory::Fd: size must be <= std::numeric_limits<int64_t>::max()")
654 .
655 operator nn::GeneralResult<Memory>();
656 }
657 if (memory.offset > std::numeric_limits<int64_t>::max()) {
658 return (
659 NN_ERROR()
660 << "Memory::Fd: offset must be <= std::numeric_limits<int64_t>::max()")
661 .
662 operator nn::GeneralResult<Memory>();
663 }
664 }
665
666 auto fd = NN_TRY(nn::dupFd(memory.fd));
667 auto handle = common::MappableFile{
668 .length = static_cast<int64_t>(memory.size),
669 .prot = memory.prot,
670 .fd = ndk::ScopedFileDescriptor(fd.release()),
671 .offset = static_cast<int64_t>(memory.offset),
672 };
673 return Memory::make<Memory::Tag::mappableFile>(std::move(handle));
674}
675
676nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::HardwareBuffer& memory) {
Ray Hernandez338d6f82021-08-11 21:29:20 +0000677#ifdef __ANDROID__
Michael Butlerf03ebd92021-03-25 15:27:38 -0700678 const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(memory.handle.get());
679 if (nativeHandle == nullptr) {
680 return (NN_ERROR() << "unvalidatedConvert failed because AHardwareBuffer_getNativeHandle "
681 "returned nullptr")
682 .
683 operator nn::GeneralResult<Memory>();
684 }
685
686 auto handle = NN_TRY(aidlHandleFromNativeHandle(*nativeHandle));
687
688 AHardwareBuffer_Desc desc;
689 AHardwareBuffer_describe(memory.handle.get(), &desc);
690
691 const auto description = graphics::common::HardwareBufferDescription{
692 .width = static_cast<int32_t>(desc.width),
693 .height = static_cast<int32_t>(desc.height),
694 .layers = static_cast<int32_t>(desc.layers),
695 .format = static_cast<graphics::common::PixelFormat>(desc.format),
696 .usage = static_cast<graphics::common::BufferUsage>(desc.usage),
697 .stride = static_cast<int32_t>(desc.stride),
698 };
699
700 auto hardwareBuffer = graphics::common::HardwareBuffer{
701 .description = std::move(description),
702 .handle = std::move(handle),
703 };
704 return Memory::make<Memory::Tag::hardwareBuffer>(std::move(hardwareBuffer));
Ray Hernandez338d6f82021-08-11 21:29:20 +0000705#else // __ANDROID__
706 LOG(FATAL) << "nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::HardwareBuffer& "
707 "memory): Not Available on Host Build";
708 (void)memory;
709 return (NN_ERROR() << "unvalidatedConvert failed").operator nn::GeneralResult<Memory>();
710#endif // __ANDROID__
Michael Butlerf03ebd92021-03-25 15:27:38 -0700711}
712
713nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Unknown& /*memory*/) {
714 return (NN_ERROR() << "Unable to convert Unknown memory type")
715 .
716 operator nn::GeneralResult<Memory>();
Michael Butlerab2f4822021-02-08 00:05:07 -0800717}
718
Michael Butler53455632021-10-25 11:20:33 -0700719nn::GeneralResult<PerformanceInfo> unvalidatedConvert(
720 const nn::Capabilities::PerformanceInfo& info) {
721 return PerformanceInfo{.execTime = info.execTime, .powerUsage = info.powerUsage};
722}
723
724nn::GeneralResult<OperandPerformance> unvalidatedConvert(
725 const nn::Capabilities::OperandPerformance& operandPerformance) {
726 return OperandPerformance{.type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
727 .info = NN_TRY(unvalidatedConvert(operandPerformance.info))};
728}
729
730nn::GeneralResult<std::vector<OperandPerformance>> unvalidatedConvert(
731 const nn::Capabilities::OperandPerformanceTable& table) {
732 std::vector<OperandPerformance> operandPerformances;
733 operandPerformances.reserve(table.asVector().size());
734 for (const auto& operandPerformance : table.asVector()) {
735 operandPerformances.push_back(NN_TRY(unvalidatedConvert(operandPerformance)));
736 }
737 return operandPerformances;
738}
739
740nn::GeneralResult<ExtensionOperandTypeInformation> unvalidatedConvert(
741 const nn::Extension::OperandTypeInformation& info) {
742 return ExtensionOperandTypeInformation{.type = info.type,
743 .isTensor = info.isTensor,
744 .byteSize = static_cast<int32_t>(info.byteSize)};
745}
746
747nn::GeneralResult<int64_t> unvalidatedConvert(const nn::Duration& duration) {
748 if (duration < nn::Duration::zero()) {
749 return NN_ERROR() << "Unable to convert invalid (negative) duration";
750 }
751 constexpr std::chrono::nanoseconds::rep kIntMax = std::numeric_limits<int64_t>::max();
752 const auto count = duration.count();
753 return static_cast<int64_t>(std::min(count, kIntMax));
754}
755
756template <typename Input>
757using UnvalidatedConvertOutput =
758 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
759
760template <typename Type>
761nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
762 const std::vector<Type>& arguments) {
763 std::vector<UnvalidatedConvertOutput<Type>> halObject;
764 halObject.reserve(arguments.size());
765 for (const auto& argument : arguments) {
766 halObject.push_back(NN_TRY(unvalidatedConvert(argument)));
767 }
768 return halObject;
769}
770
771template <typename Type>
772nn::GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& canonical) {
773 NN_TRY(compliantVersion(canonical));
774 return utils::unvalidatedConvert(canonical);
775}
776
777template <typename Type>
778nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
779 const std::vector<Type>& arguments) {
780 std::vector<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
781 for (size_t i = 0; i < arguments.size(); ++i) {
782 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
783 }
784 return halObject;
785}
786
Michael Butlerab2f4822021-02-08 00:05:07 -0800787} // namespace
788
Lev Proleev900c28a2021-01-26 19:40:20 +0000789nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(const nn::CacheToken& cacheToken) {
790 return std::vector<uint8_t>(cacheToken.begin(), cacheToken.end());
791}
792
793nn::GeneralResult<BufferDesc> unvalidatedConvert(const nn::BufferDesc& bufferDesc) {
794 return BufferDesc{.dimensions = NN_TRY(toSigned(bufferDesc.dimensions))};
795}
796
797nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRole) {
798 VERIFY_LE_INT32_MAX(bufferRole.modelIndex)
799 << "BufferRole: modelIndex must be <= std::numeric_limits<int32_t>::max()";
800 VERIFY_LE_INT32_MAX(bufferRole.ioIndex)
801 << "BufferRole: ioIndex must be <= std::numeric_limits<int32_t>::max()";
802 return BufferRole{
803 .modelIndex = static_cast<int32_t>(bufferRole.modelIndex),
804 .ioIndex = static_cast<int32_t>(bufferRole.ioIndex),
Xusong Wang3633d072021-03-19 13:58:24 -0700805 .probability = bufferRole.probability,
Lev Proleev900c28a2021-01-26 19:40:20 +0000806 };
807}
808
Michael Butler53455632021-10-25 11:20:33 -0700809nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType) {
810 switch (deviceType) {
811 case nn::DeviceType::UNKNOWN:
812 break;
813 case nn::DeviceType::OTHER:
814 case nn::DeviceType::CPU:
815 case nn::DeviceType::GPU:
816 case nn::DeviceType::ACCELERATOR:
817 return static_cast<DeviceType>(deviceType);
818 }
819 return NN_ERROR() << "Invalid DeviceType " << deviceType;
820}
821
Lev Proleev900c28a2021-01-26 19:40:20 +0000822nn::GeneralResult<bool> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
823 return measureTiming == nn::MeasureTiming::YES;
824}
825
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800826nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory) {
Michael Butlerf03ebd92021-03-25 15:27:38 -0700827 if (memory == nullptr) {
828 return (NN_ERROR() << "Unable to convert nullptr memory")
829 .
830 operator nn::GeneralResult<Memory>();
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000831 }
Michael Butlerf03ebd92021-03-25 15:27:38 -0700832 return std::visit([](const auto& x) { return unvalidatedConvert(x); }, memory->handle);
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000833}
834
835nn::GeneralResult<ErrorStatus> unvalidatedConvert(const nn::ErrorStatus& errorStatus) {
836 switch (errorStatus) {
837 case nn::ErrorStatus::NONE:
838 case nn::ErrorStatus::DEVICE_UNAVAILABLE:
839 case nn::ErrorStatus::GENERAL_FAILURE:
840 case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
841 case nn::ErrorStatus::INVALID_ARGUMENT:
842 case nn::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
843 case nn::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
844 case nn::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
845 case nn::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
846 return static_cast<ErrorStatus>(errorStatus);
847 default:
848 return ErrorStatus::GENERAL_FAILURE;
849 }
850}
851
852nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape) {
853 return OutputShape{.dimensions = NN_TRY(toSigned(outputShape.dimensions)),
854 .isSufficient = outputShape.isSufficient};
855}
856
Lev Proleev900c28a2021-01-26 19:40:20 +0000857nn::GeneralResult<ExecutionPreference> unvalidatedConvert(
858 const nn::ExecutionPreference& executionPreference) {
859 return static_cast<ExecutionPreference>(executionPreference);
860}
861
862nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butler388bceb2021-02-03 15:15:43 -0800863 if (operandType == nn::OperandType::OEM || operandType == nn::OperandType::TENSOR_OEM_BYTE) {
864 return NN_ERROR() << "Unable to convert invalid OperandType " << operandType;
865 }
Lev Proleev900c28a2021-01-26 19:40:20 +0000866 return static_cast<OperandType>(operandType);
867}
868
869nn::GeneralResult<OperandLifeTime> unvalidatedConvert(
870 const nn::Operand::LifeTime& operandLifeTime) {
871 return static_cast<OperandLifeTime>(operandLifeTime);
872}
873
874nn::GeneralResult<DataLocation> unvalidatedConvert(const nn::DataLocation& location) {
875 VERIFY_LE_INT32_MAX(location.poolIndex)
876 << "DataLocation: pool index must be <= std::numeric_limits<int32_t>::max()";
877 return DataLocation{
878 .poolIndex = static_cast<int32_t>(location.poolIndex),
879 .offset = static_cast<int64_t>(location.offset),
880 .length = static_cast<int64_t>(location.length),
881 };
882}
883
884nn::GeneralResult<std::optional<OperandExtraParams>> unvalidatedConvert(
885 const nn::Operand::ExtraParams& extraParams) {
886 return std::visit(
887 overloaded{
888 [](const nn::Operand::NoParams&)
889 -> nn::GeneralResult<std::optional<OperandExtraParams>> {
890 return std::nullopt;
891 },
892 [](const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams)
893 -> nn::GeneralResult<std::optional<OperandExtraParams>> {
894 if (symmPerChannelQuantParams.channelDim >
895 std::numeric_limits<int32_t>::max()) {
896 // Using explicit type conversion because std::optional in successful
897 // result confuses the compiler.
898 return (NN_ERROR() << "symmPerChannelQuantParams.channelDim must be <= "
899 "std::numeric_limits<int32_t>::max(), received: "
900 << symmPerChannelQuantParams.channelDim)
901 .
902 operator nn::GeneralResult<std::optional<OperandExtraParams>>();
903 }
904 return OperandExtraParams::make<OperandExtraParams::Tag::channelQuant>(
905 SymmPerChannelQuantParams{
906 .scales = symmPerChannelQuantParams.scales,
907 .channelDim = static_cast<int32_t>(
908 symmPerChannelQuantParams.channelDim),
909 });
910 },
911 [](const nn::Operand::ExtensionParams& extensionParams)
912 -> nn::GeneralResult<std::optional<OperandExtraParams>> {
913 return OperandExtraParams::make<OperandExtraParams::Tag::extension>(
914 extensionParams);
915 },
916 },
917 extraParams);
918}
919
920nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
921 return Operand{
922 .type = NN_TRY(unvalidatedConvert(operand.type)),
923 .dimensions = NN_TRY(toSigned(operand.dimensions)),
924 .scale = operand.scale,
925 .zeroPoint = operand.zeroPoint,
926 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
927 .location = NN_TRY(unvalidatedConvert(operand.location)),
928 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
929 };
930}
931
932nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butler388bceb2021-02-03 15:15:43 -0800933 if (operationType == nn::OperationType::OEM_OPERATION) {
934 return NN_ERROR() << "Unable to convert invalid OperationType OEM_OPERATION";
935 }
Lev Proleev900c28a2021-01-26 19:40:20 +0000936 return static_cast<OperationType>(operationType);
937}
938
939nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
940 return Operation{
941 .type = NN_TRY(unvalidatedConvert(operation.type)),
942 .inputs = NN_TRY(toSigned(operation.inputs)),
943 .outputs = NN_TRY(toSigned(operation.outputs)),
944 };
945}
946
947nn::GeneralResult<Subgraph> unvalidatedConvert(const nn::Model::Subgraph& subgraph) {
948 return Subgraph{
949 .operands = NN_TRY(unvalidatedConvert(subgraph.operands)),
950 .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
951 .inputIndexes = NN_TRY(toSigned(subgraph.inputIndexes)),
952 .outputIndexes = NN_TRY(toSigned(subgraph.outputIndexes)),
953 };
954}
955
956nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(
957 const nn::Model::OperandValues& operandValues) {
958 return std::vector<uint8_t>(operandValues.data(), operandValues.data() + operandValues.size());
959}
960
961nn::GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
Miao Wang0e671f32021-10-26 20:03:05 +0000962 const nn::ExtensionNameAndPrefix& extensionNameToPrefix) {
Lev Proleev900c28a2021-01-26 19:40:20 +0000963 return ExtensionNameAndPrefix{
964 .name = extensionNameToPrefix.name,
965 .prefix = extensionNameToPrefix.prefix,
966 };
967}
968
969nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
970 return Model{
971 .main = NN_TRY(unvalidatedConvert(model.main)),
972 .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
973 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
974 .pools = NN_TRY(unvalidatedConvert(model.pools)),
975 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
976 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
977 };
978}
979
980nn::GeneralResult<Priority> unvalidatedConvert(const nn::Priority& priority) {
981 return static_cast<Priority>(priority);
982}
983
984nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request) {
985 return Request{
986 .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
987 .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
988 .pools = NN_TRY(unvalidatedConvert(request.pools)),
989 };
990}
991
992nn::GeneralResult<RequestArgument> unvalidatedConvert(
993 const nn::Request::Argument& requestArgument) {
994 if (requestArgument.lifetime == nn::Request::Argument::LifeTime::POINTER) {
995 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
996 << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
997 }
998 const bool hasNoValue = requestArgument.lifetime == nn::Request::Argument::LifeTime::NO_VALUE;
999 return RequestArgument{
1000 .hasNoValue = hasNoValue,
1001 .location = NN_TRY(unvalidatedConvert(requestArgument.location)),
1002 .dimensions = NN_TRY(toSigned(requestArgument.dimensions)),
1003 };
1004}
1005
1006nn::GeneralResult<RequestMemoryPool> unvalidatedConvert(const nn::Request::MemoryPool& memoryPool) {
1007 return std::visit(
1008 overloaded{
1009 [](const nn::SharedMemory& memory) -> nn::GeneralResult<RequestMemoryPool> {
1010 return RequestMemoryPool::make<RequestMemoryPool::Tag::pool>(
1011 NN_TRY(unvalidatedConvert(memory)));
1012 },
1013 [](const nn::Request::MemoryDomainToken& token)
1014 -> nn::GeneralResult<RequestMemoryPool> {
1015 return RequestMemoryPool::make<RequestMemoryPool::Tag::token>(
1016 underlyingType(token));
1017 },
1018 [](const nn::SharedBuffer& /*buffer*/) {
1019 return (NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
1020 << "Unable to make memory pool from IBuffer")
1021 .
1022 operator nn::GeneralResult<RequestMemoryPool>();
1023 },
1024 },
1025 memoryPool);
1026}
1027
1028nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
1029 return Timing{
Lev Proleev8df7d6e2021-04-14 20:54:27 +01001030 .timeOnDeviceNs = NN_TRY(unvalidatedConvert(timing.timeOnDevice)),
1031 .timeInDriverNs = NN_TRY(unvalidatedConvert(timing.timeInDriver)),
Lev Proleev900c28a2021-01-26 19:40:20 +00001032 };
1033}
1034
Lev Proleev900c28a2021-01-26 19:40:20 +00001035nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalDuration& optionalDuration) {
1036 if (!optionalDuration.has_value()) {
1037 return kNoTiming;
1038 }
1039 return unvalidatedConvert(optionalDuration.value());
1040}
1041
1042nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalTimePoint& optionalTimePoint) {
1043 if (!optionalTimePoint.has_value()) {
1044 return kNoTiming;
1045 }
1046 return unvalidatedConvert(optionalTimePoint->time_since_epoch());
1047}
1048
1049nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SyncFence& syncFence) {
1050 auto duplicatedFd = NN_TRY(nn::dupFd(syncFence.getFd()));
1051 return ndk::ScopedFileDescriptor(duplicatedFd.release());
1052}
1053
Michael Butlere52a77e2021-06-07 13:10:58 -07001054nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SharedHandle& handle) {
1055 auto duplicatedFd = NN_TRY(nn::dupFd(handle->get()));
Lev Proleev900c28a2021-01-26 19:40:20 +00001056 return ndk::ScopedFileDescriptor(duplicatedFd.release());
1057}
1058
Michael Butler53455632021-10-25 11:20:33 -07001059nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
1060 return Capabilities{
1061 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
1062 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
1063 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
1064 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
1065 .operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance)),
1066 .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
1067 .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
1068 };
1069}
1070
1071nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
1072 return Extension{.name = extension.name,
1073 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes))};
1074}
Miao Wang0e671f32021-10-26 20:03:05 +00001075#ifdef NN_AIDL_V4_OR_ABOVE
1076nn::GeneralResult<TokenValuePair> unvalidatedConvert(const nn::TokenValuePair& tokenValuePair) {
1077 return TokenValuePair{.token = tokenValuePair.token, .value = tokenValuePair.value};
1078}
1079#endif // NN_AIDL_V4_OR_ABOVE
Michael Butler53455632021-10-25 11:20:33 -07001080
Lev Proleev900c28a2021-01-26 19:40:20 +00001081nn::GeneralResult<std::vector<uint8_t>> convert(const nn::CacheToken& cacheToken) {
Michael Butler388bceb2021-02-03 15:15:43 -08001082 return validatedConvert(cacheToken);
Lev Proleev900c28a2021-01-26 19:40:20 +00001083}
1084
1085nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc) {
1086 return validatedConvert(bufferDesc);
1087}
1088
Michael Butler53455632021-10-25 11:20:33 -07001089nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
1090 return validatedConvert(deviceType);
1091}
1092
Lev Proleev900c28a2021-01-26 19:40:20 +00001093nn::GeneralResult<bool> convert(const nn::MeasureTiming& measureTiming) {
1094 return validatedConvert(measureTiming);
1095}
1096
Michael Butlerfadeb8a2021-02-07 00:11:13 -08001097nn::GeneralResult<Memory> convert(const nn::SharedMemory& memory) {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +00001098 return validatedConvert(memory);
1099}
1100
1101nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus) {
1102 return validatedConvert(errorStatus);
1103}
1104
Lev Proleev900c28a2021-01-26 19:40:20 +00001105nn::GeneralResult<ExecutionPreference> convert(const nn::ExecutionPreference& executionPreference) {
1106 return validatedConvert(executionPreference);
1107}
1108
1109nn::GeneralResult<Model> convert(const nn::Model& model) {
1110 return validatedConvert(model);
1111}
1112
1113nn::GeneralResult<Priority> convert(const nn::Priority& priority) {
1114 return validatedConvert(priority);
1115}
1116
1117nn::GeneralResult<Request> convert(const nn::Request& request) {
1118 return validatedConvert(request);
1119}
1120
1121nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
1122 return validatedConvert(timing);
1123}
1124
1125nn::GeneralResult<int64_t> convert(const nn::OptionalDuration& optionalDuration) {
1126 return validatedConvert(optionalDuration);
1127}
1128
1129nn::GeneralResult<int64_t> convert(const nn::OptionalTimePoint& outputShapes) {
1130 return validatedConvert(outputShapes);
1131}
1132
Michael Butler53455632021-10-25 11:20:33 -07001133nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
1134 return validatedConvert(capabilities);
1135}
1136
1137nn::GeneralResult<Extension> convert(const nn::Extension& extension) {
1138 return validatedConvert(extension);
1139}
1140
Lev Proleev900c28a2021-01-26 19:40:20 +00001141nn::GeneralResult<std::vector<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
1142 return validatedConvert(bufferRoles);
1143}
1144
Lev Proleev6b6dfcd2020-11-11 18:28:50 +00001145nn::GeneralResult<std::vector<OutputShape>> convert(
1146 const std::vector<nn::OutputShape>& outputShapes) {
1147 return validatedConvert(outputShapes);
1148}
1149
Lev Proleev900c28a2021-01-26 19:40:20 +00001150nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
1151 const std::vector<nn::SharedHandle>& cacheHandles) {
Michael Butlere52a77e2021-06-07 13:10:58 -07001152 return validatedConvert(cacheHandles);
Lev Proleev900c28a2021-01-26 19:40:20 +00001153}
1154
1155nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
1156 const std::vector<nn::SyncFence>& syncFences) {
Michael Butler388bceb2021-02-03 15:15:43 -08001157 return validatedConvert(syncFences);
Lev Proleev900c28a2021-01-26 19:40:20 +00001158}
Miao Wang0e671f32021-10-26 20:03:05 +00001159nn::GeneralResult<std::vector<ExtensionNameAndPrefix>> convert(
1160 const std::vector<nn::ExtensionNameAndPrefix>& extensionNameToPrefix) {
1161 return unvalidatedConvert(extensionNameToPrefix);
1162}
1163
1164#ifdef NN_AIDL_V4_OR_ABOVE
1165nn::GeneralResult<std::vector<TokenValuePair>> convert(
1166 const std::vector<nn::TokenValuePair>& metaData) {
1167 return validatedConvert(metaData);
1168}
1169#endif // NN_AIDL_V4_OR_ABOVE
Lev Proleev900c28a2021-01-26 19:40:20 +00001170
Michael Butler53455632021-10-25 11:20:33 -07001171nn::GeneralResult<std::vector<Extension>> convert(const std::vector<nn::Extension>& extensions) {
1172 return validatedConvert(extensions);
1173}
1174
Lev Proleev6b6dfcd2020-11-11 18:28:50 +00001175nn::GeneralResult<std::vector<int32_t>> toSigned(const std::vector<uint32_t>& vec) {
1176 if (!std::all_of(vec.begin(), vec.end(),
1177 [](uint32_t v) { return v <= std::numeric_limits<int32_t>::max(); })) {
1178 return NN_ERROR() << "Vector contains a value that doesn't fit into int32_t.";
1179 }
1180 return std::vector<int32_t>(vec.begin(), vec.end());
1181}
1182
1183} // namespace aidl::android::hardware::neuralnetworks::utils