blob: d5f7f81663145516aad064556ee69b549cfa9499 [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
19#include <aidl/android/hardware/common/NativeHandle.h>
20#include <android-base/logging.h>
Lev Proleev900c28a2021-01-26 19:40:20 +000021#include <android-base/unique_fd.h>
22#include <android/binder_auto_utils.h>
Michael Butlerab2f4822021-02-08 00:05:07 -080023#include <android/hardware_buffer.h>
24#include <cutils/native_handle.h>
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000025#include <nnapi/OperandTypes.h>
26#include <nnapi/OperationTypes.h>
27#include <nnapi/Result.h>
28#include <nnapi/SharedMemory.h>
29#include <nnapi/TypeUtils.h>
30#include <nnapi/Types.h>
31#include <nnapi/Validation.h>
32#include <nnapi/hal/CommonUtils.h>
33#include <nnapi/hal/HandleError.h>
Michael Butlerab2f4822021-02-08 00:05:07 -080034#include <vndk/hardware_buffer.h>
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000035
36#include <algorithm>
37#include <chrono>
38#include <functional>
39#include <iterator>
40#include <limits>
41#include <type_traits>
42#include <utility>
43
Michael Butler388bceb2021-02-03 15:15:43 -080044#include "Utils.h"
45
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000046#define VERIFY_NON_NEGATIVE(value) \
47 while (UNLIKELY(value < 0)) return NN_ERROR()
48
Lev Proleev900c28a2021-01-26 19:40:20 +000049#define VERIFY_LE_INT32_MAX(value) \
50 while (UNLIKELY(value > std::numeric_limits<int32_t>::max())) return NN_ERROR()
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000051
Lev Proleev900c28a2021-01-26 19:40:20 +000052namespace {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000053template <typename Type>
54constexpr std::underlying_type_t<Type> underlyingType(Type value) {
55 return static_cast<std::underlying_type_t<Type>>(value);
56}
57
Lev Proleev900c28a2021-01-26 19:40:20 +000058constexpr int64_t kNoTiming = -1;
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000059
60} // namespace
61
62namespace android::nn {
63namespace {
64
Michael Butlerfadeb8a2021-02-07 00:11:13 -080065using ::aidl::android::hardware::common::NativeHandle;
66
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000067template <typename Input>
68using UnvalidatedConvertOutput =
69 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
70
71template <typename Type>
72GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
73 const std::vector<Type>& arguments) {
74 std::vector<UnvalidatedConvertOutput<Type>> canonical;
75 canonical.reserve(arguments.size());
76 for (const auto& argument : arguments) {
77 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
78 }
79 return canonical;
80}
81
82template <typename Type>
83GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
84 const std::vector<Type>& arguments) {
85 return unvalidatedConvertVec(arguments);
86}
87
88template <typename Type>
89GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& halObject) {
90 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
Michael Butler388bceb2021-02-03 15:15:43 -080091 NN_TRY(aidl_hal::utils::compliantVersion(canonical));
Lev Proleev6b6dfcd2020-11-11 18:28:50 +000092 return canonical;
93}
94
95template <typename Type>
96GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
97 const std::vector<Type>& arguments) {
98 std::vector<UnvalidatedConvertOutput<Type>> canonical;
99 canonical.reserve(arguments.size());
100 for (const auto& argument : arguments) {
101 canonical.push_back(NN_TRY(validatedConvert(argument)));
102 }
103 return canonical;
104}
105
Michael Butlerab2f4822021-02-08 00:05:07 -0800106GeneralResult<Handle> unvalidatedConvertHelper(const NativeHandle& aidlNativeHandle) {
107 std::vector<base::unique_fd> fds;
108 fds.reserve(aidlNativeHandle.fds.size());
109 for (const auto& fd : aidlNativeHandle.fds) {
Lev Proleev900c28a2021-01-26 19:40:20 +0000110 auto duplicatedFd = NN_TRY(dupFd(fd.get()));
111 fds.emplace_back(duplicatedFd.release());
Michael Butlerab2f4822021-02-08 00:05:07 -0800112 }
113
114 return Handle{.fds = std::move(fds), .ints = aidlNativeHandle.ints};
115}
116
117struct NativeHandleDeleter {
118 void operator()(native_handle_t* handle) const {
119 if (handle) {
120 native_handle_close(handle);
121 native_handle_delete(handle);
122 }
123 }
124};
125
126using UniqueNativeHandle = std::unique_ptr<native_handle_t, NativeHandleDeleter>;
127
Lev Proleev900c28a2021-01-26 19:40:20 +0000128static GeneralResult<UniqueNativeHandle> nativeHandleFromAidlHandle(const NativeHandle& handle) {
Michael Butlerab2f4822021-02-08 00:05:07 -0800129 std::vector<base::unique_fd> fds;
130 fds.reserve(handle.fds.size());
131 for (const auto& fd : handle.fds) {
Lev Proleev900c28a2021-01-26 19:40:20 +0000132 auto duplicatedFd = NN_TRY(dupFd(fd.get()));
133 fds.emplace_back(duplicatedFd.release());
Michael Butlerab2f4822021-02-08 00:05:07 -0800134 }
135
136 constexpr size_t kIntMax = std::numeric_limits<int>::max();
137 CHECK_LE(handle.fds.size(), kIntMax);
138 CHECK_LE(handle.ints.size(), kIntMax);
139 native_handle_t* nativeHandle = native_handle_create(static_cast<int>(handle.fds.size()),
140 static_cast<int>(handle.ints.size()));
141 if (nativeHandle == nullptr) {
142 return NN_ERROR() << "Failed to create native_handle";
143 }
144 for (size_t i = 0; i < fds.size(); ++i) {
145 nativeHandle->data[i] = fds[i].release();
146 }
147 std::copy(handle.ints.begin(), handle.ints.end(), &nativeHandle->data[nativeHandle->numFds]);
148
149 return UniqueNativeHandle(nativeHandle);
150}
151
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000152} // anonymous namespace
153
154GeneralResult<OperandType> unvalidatedConvert(const aidl_hal::OperandType& operandType) {
155 VERIFY_NON_NEGATIVE(underlyingType(operandType)) << "Negative operand types are not allowed.";
Michael Butler388bceb2021-02-03 15:15:43 -0800156 const auto canonical = static_cast<OperandType>(operandType);
157 if (canonical == OperandType::OEM || canonical == OperandType::TENSOR_OEM_BYTE) {
158 return NN_ERROR() << "Unable to convert invalid OperandType " << canonical;
159 }
160 return canonical;
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000161}
162
163GeneralResult<OperationType> unvalidatedConvert(const aidl_hal::OperationType& operationType) {
164 VERIFY_NON_NEGATIVE(underlyingType(operationType))
165 << "Negative operation types are not allowed.";
Michael Butler388bceb2021-02-03 15:15:43 -0800166 const auto canonical = static_cast<OperationType>(operationType);
167 if (canonical == OperationType::OEM_OPERATION) {
168 return NN_ERROR() << "Unable to convert invalid OperationType OEM_OPERATION";
169 }
170 return canonical;
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000171}
172
173GeneralResult<DeviceType> unvalidatedConvert(const aidl_hal::DeviceType& deviceType) {
174 return static_cast<DeviceType>(deviceType);
175}
176
177GeneralResult<Priority> unvalidatedConvert(const aidl_hal::Priority& priority) {
178 return static_cast<Priority>(priority);
179}
180
181GeneralResult<Capabilities> unvalidatedConvert(const aidl_hal::Capabilities& capabilities) {
182 const bool validOperandTypes = std::all_of(
183 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
184 [](const aidl_hal::OperandPerformance& operandPerformance) {
Michael Butler388bceb2021-02-03 15:15:43 -0800185 return validatedConvert(operandPerformance.type).has_value();
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000186 });
187 if (!validOperandTypes) {
188 return NN_ERROR() << "Invalid OperandType when unvalidatedConverting OperandPerformance in "
189 "Capabilities";
190 }
191
192 auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
193 auto table = NN_TRY(hal::utils::makeGeneralFailure(
194 Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
195 nn::ErrorStatus::GENERAL_FAILURE));
196
197 return Capabilities{
198 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
199 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
200 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
201 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
202 .operandPerformance = std::move(table),
203 .ifPerformance = NN_TRY(unvalidatedConvert(capabilities.ifPerformance)),
204 .whilePerformance = NN_TRY(unvalidatedConvert(capabilities.whilePerformance)),
205 };
206}
207
208GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
209 const aidl_hal::OperandPerformance& operandPerformance) {
210 return Capabilities::OperandPerformance{
211 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
212 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
213 };
214}
215
216GeneralResult<Capabilities::PerformanceInfo> unvalidatedConvert(
217 const aidl_hal::PerformanceInfo& performanceInfo) {
218 return Capabilities::PerformanceInfo{
219 .execTime = performanceInfo.execTime,
220 .powerUsage = performanceInfo.powerUsage,
221 };
222}
223
224GeneralResult<DataLocation> unvalidatedConvert(const aidl_hal::DataLocation& location) {
225 VERIFY_NON_NEGATIVE(location.poolIndex) << "DataLocation: pool index must not be negative";
226 VERIFY_NON_NEGATIVE(location.offset) << "DataLocation: offset must not be negative";
227 VERIFY_NON_NEGATIVE(location.length) << "DataLocation: length must not be negative";
Xusong Wang5e36ca02021-02-16 10:40:32 -0800228 VERIFY_NON_NEGATIVE(location.padding) << "DataLocation: padding must not be negative";
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000229 if (location.offset > std::numeric_limits<uint32_t>::max()) {
230 return NN_ERROR() << "DataLocation: offset must be <= std::numeric_limits<uint32_t>::max()";
231 }
232 if (location.length > std::numeric_limits<uint32_t>::max()) {
233 return NN_ERROR() << "DataLocation: length must be <= std::numeric_limits<uint32_t>::max()";
234 }
Xusong Wang5e36ca02021-02-16 10:40:32 -0800235 if (location.padding > std::numeric_limits<uint32_t>::max()) {
236 return NN_ERROR()
237 << "DataLocation: padding must be <= std::numeric_limits<uint32_t>::max()";
238 }
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000239 return DataLocation{
240 .poolIndex = static_cast<uint32_t>(location.poolIndex),
241 .offset = static_cast<uint32_t>(location.offset),
242 .length = static_cast<uint32_t>(location.length),
Xusong Wang5e36ca02021-02-16 10:40:32 -0800243 .padding = static_cast<uint32_t>(location.padding),
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000244 };
245}
246
247GeneralResult<Operation> unvalidatedConvert(const aidl_hal::Operation& operation) {
248 return Operation{
249 .type = NN_TRY(unvalidatedConvert(operation.type)),
250 .inputs = NN_TRY(toUnsigned(operation.inputs)),
251 .outputs = NN_TRY(toUnsigned(operation.outputs)),
252 };
253}
254
255GeneralResult<Operand::LifeTime> unvalidatedConvert(
256 const aidl_hal::OperandLifeTime& operandLifeTime) {
257 return static_cast<Operand::LifeTime>(operandLifeTime);
258}
259
260GeneralResult<Operand> unvalidatedConvert(const aidl_hal::Operand& operand) {
261 return Operand{
262 .type = NN_TRY(unvalidatedConvert(operand.type)),
263 .dimensions = NN_TRY(toUnsigned(operand.dimensions)),
264 .scale = operand.scale,
265 .zeroPoint = operand.zeroPoint,
266 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
267 .location = NN_TRY(unvalidatedConvert(operand.location)),
268 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
269 };
270}
271
272GeneralResult<Operand::ExtraParams> unvalidatedConvert(
273 const std::optional<aidl_hal::OperandExtraParams>& optionalExtraParams) {
274 if (!optionalExtraParams.has_value()) {
275 return Operand::NoParams{};
276 }
277 const auto& extraParams = optionalExtraParams.value();
278 using Tag = aidl_hal::OperandExtraParams::Tag;
279 switch (extraParams.getTag()) {
280 case Tag::channelQuant:
281 return unvalidatedConvert(extraParams.get<Tag::channelQuant>());
282 case Tag::extension:
283 return extraParams.get<Tag::extension>();
284 }
285 return NN_ERROR() << "Unrecognized Operand::ExtraParams tag: "
286 << underlyingType(extraParams.getTag());
287}
288
289GeneralResult<Operand::SymmPerChannelQuantParams> unvalidatedConvert(
290 const aidl_hal::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
291 VERIFY_NON_NEGATIVE(symmPerChannelQuantParams.channelDim)
292 << "Per-channel quantization channel dimension must not be negative.";
293 return Operand::SymmPerChannelQuantParams{
294 .scales = symmPerChannelQuantParams.scales,
295 .channelDim = static_cast<uint32_t>(symmPerChannelQuantParams.channelDim),
296 };
297}
298
299GeneralResult<Model> unvalidatedConvert(const aidl_hal::Model& model) {
300 return Model{
301 .main = NN_TRY(unvalidatedConvert(model.main)),
302 .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
303 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
304 .pools = NN_TRY(unvalidatedConvert(model.pools)),
305 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
306 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
307 };
308}
309
310GeneralResult<Model::Subgraph> unvalidatedConvert(const aidl_hal::Subgraph& subgraph) {
311 return Model::Subgraph{
312 .operands = NN_TRY(unvalidatedConvert(subgraph.operands)),
313 .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
314 .inputIndexes = NN_TRY(toUnsigned(subgraph.inputIndexes)),
315 .outputIndexes = NN_TRY(toUnsigned(subgraph.outputIndexes)),
316 };
317}
318
319GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
320 const aidl_hal::ExtensionNameAndPrefix& extensionNameAndPrefix) {
321 return Model::ExtensionNameAndPrefix{
322 .name = extensionNameAndPrefix.name,
323 .prefix = extensionNameAndPrefix.prefix,
324 };
325}
326
327GeneralResult<Extension> unvalidatedConvert(const aidl_hal::Extension& extension) {
328 return Extension{
329 .name = extension.name,
330 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
331 };
332}
333
334GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
335 const aidl_hal::ExtensionOperandTypeInformation& operandTypeInformation) {
336 VERIFY_NON_NEGATIVE(operandTypeInformation.byteSize)
337 << "Extension operand type byte size must not be negative";
338 return Extension::OperandTypeInformation{
339 .type = operandTypeInformation.type,
340 .isTensor = operandTypeInformation.isTensor,
341 .byteSize = static_cast<uint32_t>(operandTypeInformation.byteSize),
342 };
343}
344
345GeneralResult<OutputShape> unvalidatedConvert(const aidl_hal::OutputShape& outputShape) {
346 return OutputShape{
347 .dimensions = NN_TRY(toUnsigned(outputShape.dimensions)),
348 .isSufficient = outputShape.isSufficient,
349 };
350}
351
352GeneralResult<MeasureTiming> unvalidatedConvert(bool measureTiming) {
353 return measureTiming ? MeasureTiming::YES : MeasureTiming::NO;
354}
355
Michael Butlerab2f4822021-02-08 00:05:07 -0800356static uint32_t roundUpToMultiple(uint32_t value, uint32_t multiple) {
357 return (value + multiple - 1) / multiple * multiple;
358}
359
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800360GeneralResult<SharedMemory> unvalidatedConvert(const aidl_hal::Memory& memory) {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000361 VERIFY_NON_NEGATIVE(memory.size) << "Memory size must not be negative";
Lev Proleev900c28a2021-01-26 19:40:20 +0000362 if (memory.size > std::numeric_limits<size_t>::max()) {
Michael Butlerab2f4822021-02-08 00:05:07 -0800363 return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
364 }
365
366 if (memory.name != "hardware_buffer_blob") {
367 return std::make_shared<const Memory>(Memory{
368 .handle = NN_TRY(unvalidatedConvertHelper(memory.handle)),
Lev Proleev900c28a2021-01-26 19:40:20 +0000369 .size = static_cast<size_t>(memory.size),
Michael Butlerab2f4822021-02-08 00:05:07 -0800370 .name = memory.name,
371 });
372 }
373
374 const auto size = static_cast<uint32_t>(memory.size);
375 const auto format = AHARDWAREBUFFER_FORMAT_BLOB;
376 const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
377 const uint32_t width = size;
378 const uint32_t height = 1; // height is always 1 for BLOB mode AHardwareBuffer.
379 const uint32_t layers = 1; // layers is always 1 for BLOB mode AHardwareBuffer.
380
381 const UniqueNativeHandle handle = NN_TRY(nativeHandleFromAidlHandle(memory.handle));
382 const native_handle_t* nativeHandle = handle.get();
383
384 // AHardwareBuffer_createFromHandle() might fail because an allocator
385 // expects a specific stride value. In that case, we try to guess it by
386 // aligning the width to small powers of 2.
387 // TODO(b/174120849): Avoid stride assumptions.
388 AHardwareBuffer* hardwareBuffer = nullptr;
389 status_t status = UNKNOWN_ERROR;
390 for (uint32_t alignment : {1, 4, 32, 64, 128, 2, 8, 16}) {
391 const uint32_t stride = roundUpToMultiple(width, alignment);
392 AHardwareBuffer_Desc desc{
393 .width = width,
394 .height = height,
395 .layers = layers,
396 .format = format,
397 .usage = usage,
398 .stride = stride,
399 };
400 status = AHardwareBuffer_createFromHandle(&desc, nativeHandle,
401 AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
402 &hardwareBuffer);
403 if (status == NO_ERROR) {
404 break;
405 }
406 }
407 if (status != NO_ERROR) {
408 return NN_ERROR(ErrorStatus::GENERAL_FAILURE)
409 << "Can't create AHardwareBuffer from handle. Error: " << status;
410 }
411
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800412 return std::make_shared<const Memory>(Memory{
Michael Butlerab2f4822021-02-08 00:05:07 -0800413 .handle = HardwareBufferHandle(hardwareBuffer, /*takeOwnership=*/true),
Lev Proleev900c28a2021-01-26 19:40:20 +0000414 .size = static_cast<size_t>(memory.size),
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000415 .name = memory.name,
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800416 });
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000417}
418
Lev Proleev900c28a2021-01-26 19:40:20 +0000419GeneralResult<Timing> unvalidatedConvert(const aidl_hal::Timing& timing) {
420 if (timing.timeInDriver < -1) {
421 return NN_ERROR() << "Timing: timeInDriver must not be less than -1";
422 }
423 if (timing.timeOnDevice < -1) {
424 return NN_ERROR() << "Timing: timeOnDevice must not be less than -1";
425 }
426 constexpr auto convertTiming = [](int64_t halTiming) -> OptionalDuration {
427 if (halTiming == kNoTiming) {
428 return {};
429 }
430 return nn::Duration(static_cast<uint64_t>(halTiming));
431 };
432 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
433 .timeInDriver = convertTiming(timing.timeInDriver)};
434}
435
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000436GeneralResult<Model::OperandValues> unvalidatedConvert(const std::vector<uint8_t>& operandValues) {
437 return Model::OperandValues(operandValues.data(), operandValues.size());
438}
439
440GeneralResult<BufferDesc> unvalidatedConvert(const aidl_hal::BufferDesc& bufferDesc) {
441 return BufferDesc{.dimensions = NN_TRY(toUnsigned(bufferDesc.dimensions))};
442}
443
444GeneralResult<BufferRole> unvalidatedConvert(const aidl_hal::BufferRole& bufferRole) {
445 VERIFY_NON_NEGATIVE(bufferRole.modelIndex) << "BufferRole: modelIndex must not be negative";
446 VERIFY_NON_NEGATIVE(bufferRole.ioIndex) << "BufferRole: ioIndex must not be negative";
447 return BufferRole{
448 .modelIndex = static_cast<uint32_t>(bufferRole.modelIndex),
449 .ioIndex = static_cast<uint32_t>(bufferRole.ioIndex),
Xusong Wang3633d072021-03-19 13:58:24 -0700450 .probability = bufferRole.probability,
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000451 };
452}
453
454GeneralResult<Request> unvalidatedConvert(const aidl_hal::Request& request) {
455 return Request{
456 .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
457 .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
458 .pools = NN_TRY(unvalidatedConvert(request.pools)),
459 };
460}
461
462GeneralResult<Request::Argument> unvalidatedConvert(const aidl_hal::RequestArgument& argument) {
463 const auto lifetime = argument.hasNoValue ? Request::Argument::LifeTime::NO_VALUE
464 : Request::Argument::LifeTime::POOL;
465 return Request::Argument{
466 .lifetime = lifetime,
467 .location = NN_TRY(unvalidatedConvert(argument.location)),
468 .dimensions = NN_TRY(toUnsigned(argument.dimensions)),
469 };
470}
471
472GeneralResult<Request::MemoryPool> unvalidatedConvert(
473 const aidl_hal::RequestMemoryPool& memoryPool) {
474 using Tag = aidl_hal::RequestMemoryPool::Tag;
475 switch (memoryPool.getTag()) {
476 case Tag::pool:
477 return unvalidatedConvert(memoryPool.get<Tag::pool>());
478 case Tag::token: {
479 const auto token = memoryPool.get<Tag::token>();
480 VERIFY_NON_NEGATIVE(token) << "Memory pool token must not be negative";
481 return static_cast<Request::MemoryDomainToken>(token);
482 }
483 }
484 return NN_ERROR() << "Invalid Request::MemoryPool tag " << underlyingType(memoryPool.getTag());
485}
486
487GeneralResult<ErrorStatus> unvalidatedConvert(const aidl_hal::ErrorStatus& status) {
488 switch (status) {
489 case aidl_hal::ErrorStatus::NONE:
490 case aidl_hal::ErrorStatus::DEVICE_UNAVAILABLE:
491 case aidl_hal::ErrorStatus::GENERAL_FAILURE:
492 case aidl_hal::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
493 case aidl_hal::ErrorStatus::INVALID_ARGUMENT:
494 case aidl_hal::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
495 case aidl_hal::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
496 case aidl_hal::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
497 case aidl_hal::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
498 return static_cast<ErrorStatus>(status);
499 }
500 return NN_ERROR() << "Invalid ErrorStatus " << underlyingType(status);
501}
502
503GeneralResult<ExecutionPreference> unvalidatedConvert(
504 const aidl_hal::ExecutionPreference& executionPreference) {
505 return static_cast<ExecutionPreference>(executionPreference);
506}
507
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800508GeneralResult<SharedHandle> unvalidatedConvert(const NativeHandle& aidlNativeHandle) {
Michael Butlerab2f4822021-02-08 00:05:07 -0800509 return std::make_shared<const Handle>(NN_TRY(unvalidatedConvertHelper(aidlNativeHandle)));
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000510}
511
Michael Butler388bceb2021-02-03 15:15:43 -0800512GeneralResult<std::vector<Operation>> unvalidatedConvert(
513 const std::vector<aidl_hal::Operation>& operations) {
514 return unvalidatedConvertVec(operations);
515}
516
Lev Proleev900c28a2021-01-26 19:40:20 +0000517GeneralResult<SyncFence> unvalidatedConvert(const ndk::ScopedFileDescriptor& syncFence) {
518 auto duplicatedFd = NN_TRY(dupFd(syncFence.get()));
519 return SyncFence::create(std::move(duplicatedFd));
520}
521
522GeneralResult<Capabilities> convert(const aidl_hal::Capabilities& capabilities) {
523 return validatedConvert(capabilities);
524}
525
526GeneralResult<DeviceType> convert(const aidl_hal::DeviceType& deviceType) {
527 return validatedConvert(deviceType);
528}
529
530GeneralResult<ErrorStatus> convert(const aidl_hal::ErrorStatus& errorStatus) {
531 return validatedConvert(errorStatus);
532}
533
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000534GeneralResult<ExecutionPreference> convert(
535 const aidl_hal::ExecutionPreference& executionPreference) {
536 return validatedConvert(executionPreference);
537}
538
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800539GeneralResult<SharedMemory> convert(const aidl_hal::Memory& operand) {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000540 return validatedConvert(operand);
541}
542
543GeneralResult<Model> convert(const aidl_hal::Model& model) {
544 return validatedConvert(model);
545}
546
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000547GeneralResult<OperandType> convert(const aidl_hal::OperandType& operandType) {
Michael Butler388bceb2021-02-03 15:15:43 -0800548 return validatedConvert(operandType);
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000549}
550
551GeneralResult<Priority> convert(const aidl_hal::Priority& priority) {
552 return validatedConvert(priority);
553}
554
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000555GeneralResult<Request> convert(const aidl_hal::Request& request) {
556 return validatedConvert(request);
557}
558
Lev Proleev900c28a2021-01-26 19:40:20 +0000559GeneralResult<Timing> convert(const aidl_hal::Timing& timing) {
560 return validatedConvert(timing);
561}
562
563GeneralResult<SyncFence> convert(const ndk::ScopedFileDescriptor& syncFence) {
Michael Butler388bceb2021-02-03 15:15:43 -0800564 return validatedConvert(syncFence);
Lev Proleev900c28a2021-01-26 19:40:20 +0000565}
566
567GeneralResult<std::vector<Extension>> convert(const std::vector<aidl_hal::Extension>& extension) {
568 return validatedConvert(extension);
569}
570
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800571GeneralResult<std::vector<SharedMemory>> convert(const std::vector<aidl_hal::Memory>& memories) {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000572 return validatedConvert(memories);
573}
574
Lev Proleev900c28a2021-01-26 19:40:20 +0000575GeneralResult<std::vector<OutputShape>> convert(
576 const std::vector<aidl_hal::OutputShape>& outputShapes) {
577 return validatedConvert(outputShapes);
578}
579
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000580GeneralResult<std::vector<uint32_t>> toUnsigned(const std::vector<int32_t>& vec) {
581 if (!std::all_of(vec.begin(), vec.end(), [](int32_t v) { return v >= 0; })) {
582 return NN_ERROR() << "Negative value passed to conversion from signed to unsigned";
583 }
584 return std::vector<uint32_t>(vec.begin(), vec.end());
585}
586
587} // namespace android::nn
588
589namespace aidl::android::hardware::neuralnetworks::utils {
590namespace {
591
592template <typename Input>
593using UnvalidatedConvertOutput =
594 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
595
596template <typename Type>
597nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
598 const std::vector<Type>& arguments) {
Lev Proleev900c28a2021-01-26 19:40:20 +0000599 std::vector<UnvalidatedConvertOutput<Type>> halObject;
600 halObject.reserve(arguments.size());
601 for (const auto& argument : arguments) {
602 halObject.push_back(NN_TRY(unvalidatedConvert(argument)));
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000603 }
604 return halObject;
605}
606
607template <typename Type>
Lev Proleev900c28a2021-01-26 19:40:20 +0000608nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
609 const std::vector<Type>& arguments) {
610 return unvalidatedConvertVec(arguments);
611}
612
613template <typename Type>
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000614nn::GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& canonical) {
Michael Butler388bceb2021-02-03 15:15:43 -0800615 NN_TRY(compliantVersion(canonical));
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000616 return utils::unvalidatedConvert(canonical);
617}
618
619template <typename Type>
620nn::GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
621 const std::vector<Type>& arguments) {
622 std::vector<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
623 for (size_t i = 0; i < arguments.size(); ++i) {
624 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
625 }
626 return halObject;
627}
628
Michael Butlerab2f4822021-02-08 00:05:07 -0800629nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::Handle& handle) {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000630 common::NativeHandle aidlNativeHandle;
Michael Butlerab2f4822021-02-08 00:05:07 -0800631 aidlNativeHandle.fds.reserve(handle.fds.size());
632 for (const auto& fd : handle.fds) {
Lev Proleev900c28a2021-01-26 19:40:20 +0000633 auto duplicatedFd = NN_TRY(nn::dupFd(fd.get()));
634 aidlNativeHandle.fds.emplace_back(duplicatedFd.release());
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000635 }
Michael Butlerab2f4822021-02-08 00:05:07 -0800636 aidlNativeHandle.ints = handle.ints;
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000637 return aidlNativeHandle;
638}
639
Lev Proleev900c28a2021-01-26 19:40:20 +0000640// Helper template for std::visit
641template <class... Ts>
642struct overloaded : Ts... {
643 using Ts::operator()...;
644};
645template <class... Ts>
646overloaded(Ts...)->overloaded<Ts...>;
647
Michael Butlerab2f4822021-02-08 00:05:07 -0800648static nn::GeneralResult<common::NativeHandle> aidlHandleFromNativeHandle(
649 const native_handle_t& handle) {
650 common::NativeHandle aidlNativeHandle;
651
652 aidlNativeHandle.fds.reserve(handle.numFds);
653 for (int i = 0; i < handle.numFds; ++i) {
Lev Proleev900c28a2021-01-26 19:40:20 +0000654 auto duplicatedFd = NN_TRY(nn::dupFd(handle.data[i]));
655 aidlNativeHandle.fds.emplace_back(duplicatedFd.release());
Michael Butlerab2f4822021-02-08 00:05:07 -0800656 }
657
658 aidlNativeHandle.ints = std::vector<int>(&handle.data[handle.numFds],
659 &handle.data[handle.numFds + handle.numInts]);
660
661 return aidlNativeHandle;
662}
663
664} // namespace
665
Lev Proleev900c28a2021-01-26 19:40:20 +0000666nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(const nn::CacheToken& cacheToken) {
667 return std::vector<uint8_t>(cacheToken.begin(), cacheToken.end());
668}
669
670nn::GeneralResult<BufferDesc> unvalidatedConvert(const nn::BufferDesc& bufferDesc) {
671 return BufferDesc{.dimensions = NN_TRY(toSigned(bufferDesc.dimensions))};
672}
673
674nn::GeneralResult<BufferRole> unvalidatedConvert(const nn::BufferRole& bufferRole) {
675 VERIFY_LE_INT32_MAX(bufferRole.modelIndex)
676 << "BufferRole: modelIndex must be <= std::numeric_limits<int32_t>::max()";
677 VERIFY_LE_INT32_MAX(bufferRole.ioIndex)
678 << "BufferRole: ioIndex must be <= std::numeric_limits<int32_t>::max()";
679 return BufferRole{
680 .modelIndex = static_cast<int32_t>(bufferRole.modelIndex),
681 .ioIndex = static_cast<int32_t>(bufferRole.ioIndex),
Xusong Wang3633d072021-03-19 13:58:24 -0700682 .probability = bufferRole.probability,
Lev Proleev900c28a2021-01-26 19:40:20 +0000683 };
684}
685
686nn::GeneralResult<bool> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
687 return measureTiming == nn::MeasureTiming::YES;
688}
689
Michael Butlerab2f4822021-02-08 00:05:07 -0800690nn::GeneralResult<common::NativeHandle> unvalidatedConvert(const nn::SharedHandle& sharedHandle) {
691 CHECK(sharedHandle != nullptr);
692 return unvalidatedConvert(*sharedHandle);
693}
694
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800695nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory) {
696 CHECK(memory != nullptr);
697 if (memory->size > std::numeric_limits<int64_t>::max()) {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000698 return NN_ERROR() << "Memory size doesn't fit into int64_t.";
699 }
Michael Butlerab2f4822021-02-08 00:05:07 -0800700 if (const auto* handle = std::get_if<nn::Handle>(&memory->handle)) {
701 return Memory{
702 .handle = NN_TRY(unvalidatedConvert(*handle)),
703 .size = static_cast<int64_t>(memory->size),
704 .name = memory->name,
705 };
706 }
707
708 const auto* ahwb = std::get<nn::HardwareBufferHandle>(memory->handle).get();
709 AHardwareBuffer_Desc bufferDesc;
710 AHardwareBuffer_describe(ahwb, &bufferDesc);
711
712 if (bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
713 CHECK_EQ(memory->size, bufferDesc.width);
714 CHECK_EQ(memory->name, "hardware_buffer_blob");
715 } else {
716 CHECK_EQ(memory->size, 0u);
717 CHECK_EQ(memory->name, "hardware_buffer");
718 }
719
720 const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
721 if (nativeHandle == nullptr) {
722 return NN_ERROR() << "unvalidatedConvert failed because AHardwareBuffer_getNativeHandle "
723 "returned nullptr";
724 }
725
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000726 return Memory{
Michael Butlerab2f4822021-02-08 00:05:07 -0800727 .handle = NN_TRY(aidlHandleFromNativeHandle(*nativeHandle)),
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800728 .size = static_cast<int64_t>(memory->size),
729 .name = memory->name,
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000730 };
731}
732
733nn::GeneralResult<ErrorStatus> unvalidatedConvert(const nn::ErrorStatus& errorStatus) {
734 switch (errorStatus) {
735 case nn::ErrorStatus::NONE:
736 case nn::ErrorStatus::DEVICE_UNAVAILABLE:
737 case nn::ErrorStatus::GENERAL_FAILURE:
738 case nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
739 case nn::ErrorStatus::INVALID_ARGUMENT:
740 case nn::ErrorStatus::MISSED_DEADLINE_TRANSIENT:
741 case nn::ErrorStatus::MISSED_DEADLINE_PERSISTENT:
742 case nn::ErrorStatus::RESOURCE_EXHAUSTED_TRANSIENT:
743 case nn::ErrorStatus::RESOURCE_EXHAUSTED_PERSISTENT:
744 return static_cast<ErrorStatus>(errorStatus);
745 default:
746 return ErrorStatus::GENERAL_FAILURE;
747 }
748}
749
750nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape) {
751 return OutputShape{.dimensions = NN_TRY(toSigned(outputShape.dimensions)),
752 .isSufficient = outputShape.isSufficient};
753}
754
Lev Proleev900c28a2021-01-26 19:40:20 +0000755nn::GeneralResult<ExecutionPreference> unvalidatedConvert(
756 const nn::ExecutionPreference& executionPreference) {
757 return static_cast<ExecutionPreference>(executionPreference);
758}
759
760nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butler388bceb2021-02-03 15:15:43 -0800761 if (operandType == nn::OperandType::OEM || operandType == nn::OperandType::TENSOR_OEM_BYTE) {
762 return NN_ERROR() << "Unable to convert invalid OperandType " << operandType;
763 }
Lev Proleev900c28a2021-01-26 19:40:20 +0000764 return static_cast<OperandType>(operandType);
765}
766
767nn::GeneralResult<OperandLifeTime> unvalidatedConvert(
768 const nn::Operand::LifeTime& operandLifeTime) {
769 return static_cast<OperandLifeTime>(operandLifeTime);
770}
771
772nn::GeneralResult<DataLocation> unvalidatedConvert(const nn::DataLocation& location) {
773 VERIFY_LE_INT32_MAX(location.poolIndex)
774 << "DataLocation: pool index must be <= std::numeric_limits<int32_t>::max()";
775 return DataLocation{
776 .poolIndex = static_cast<int32_t>(location.poolIndex),
777 .offset = static_cast<int64_t>(location.offset),
778 .length = static_cast<int64_t>(location.length),
779 };
780}
781
782nn::GeneralResult<std::optional<OperandExtraParams>> unvalidatedConvert(
783 const nn::Operand::ExtraParams& extraParams) {
784 return std::visit(
785 overloaded{
786 [](const nn::Operand::NoParams&)
787 -> nn::GeneralResult<std::optional<OperandExtraParams>> {
788 return std::nullopt;
789 },
790 [](const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams)
791 -> nn::GeneralResult<std::optional<OperandExtraParams>> {
792 if (symmPerChannelQuantParams.channelDim >
793 std::numeric_limits<int32_t>::max()) {
794 // Using explicit type conversion because std::optional in successful
795 // result confuses the compiler.
796 return (NN_ERROR() << "symmPerChannelQuantParams.channelDim must be <= "
797 "std::numeric_limits<int32_t>::max(), received: "
798 << symmPerChannelQuantParams.channelDim)
799 .
800 operator nn::GeneralResult<std::optional<OperandExtraParams>>();
801 }
802 return OperandExtraParams::make<OperandExtraParams::Tag::channelQuant>(
803 SymmPerChannelQuantParams{
804 .scales = symmPerChannelQuantParams.scales,
805 .channelDim = static_cast<int32_t>(
806 symmPerChannelQuantParams.channelDim),
807 });
808 },
809 [](const nn::Operand::ExtensionParams& extensionParams)
810 -> nn::GeneralResult<std::optional<OperandExtraParams>> {
811 return OperandExtraParams::make<OperandExtraParams::Tag::extension>(
812 extensionParams);
813 },
814 },
815 extraParams);
816}
817
818nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
819 return Operand{
820 .type = NN_TRY(unvalidatedConvert(operand.type)),
821 .dimensions = NN_TRY(toSigned(operand.dimensions)),
822 .scale = operand.scale,
823 .zeroPoint = operand.zeroPoint,
824 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
825 .location = NN_TRY(unvalidatedConvert(operand.location)),
826 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
827 };
828}
829
830nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butler388bceb2021-02-03 15:15:43 -0800831 if (operationType == nn::OperationType::OEM_OPERATION) {
832 return NN_ERROR() << "Unable to convert invalid OperationType OEM_OPERATION";
833 }
Lev Proleev900c28a2021-01-26 19:40:20 +0000834 return static_cast<OperationType>(operationType);
835}
836
837nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
838 return Operation{
839 .type = NN_TRY(unvalidatedConvert(operation.type)),
840 .inputs = NN_TRY(toSigned(operation.inputs)),
841 .outputs = NN_TRY(toSigned(operation.outputs)),
842 };
843}
844
845nn::GeneralResult<Subgraph> unvalidatedConvert(const nn::Model::Subgraph& subgraph) {
846 return Subgraph{
847 .operands = NN_TRY(unvalidatedConvert(subgraph.operands)),
848 .operations = NN_TRY(unvalidatedConvert(subgraph.operations)),
849 .inputIndexes = NN_TRY(toSigned(subgraph.inputIndexes)),
850 .outputIndexes = NN_TRY(toSigned(subgraph.outputIndexes)),
851 };
852}
853
854nn::GeneralResult<std::vector<uint8_t>> unvalidatedConvert(
855 const nn::Model::OperandValues& operandValues) {
856 return std::vector<uint8_t>(operandValues.data(), operandValues.data() + operandValues.size());
857}
858
859nn::GeneralResult<ExtensionNameAndPrefix> unvalidatedConvert(
860 const nn::Model::ExtensionNameAndPrefix& extensionNameToPrefix) {
861 return ExtensionNameAndPrefix{
862 .name = extensionNameToPrefix.name,
863 .prefix = extensionNameToPrefix.prefix,
864 };
865}
866
867nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
868 return Model{
869 .main = NN_TRY(unvalidatedConvert(model.main)),
870 .referenced = NN_TRY(unvalidatedConvert(model.referenced)),
871 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
872 .pools = NN_TRY(unvalidatedConvert(model.pools)),
873 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
874 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
875 };
876}
877
878nn::GeneralResult<Priority> unvalidatedConvert(const nn::Priority& priority) {
879 return static_cast<Priority>(priority);
880}
881
882nn::GeneralResult<Request> unvalidatedConvert(const nn::Request& request) {
883 return Request{
884 .inputs = NN_TRY(unvalidatedConvert(request.inputs)),
885 .outputs = NN_TRY(unvalidatedConvert(request.outputs)),
886 .pools = NN_TRY(unvalidatedConvert(request.pools)),
887 };
888}
889
890nn::GeneralResult<RequestArgument> unvalidatedConvert(
891 const nn::Request::Argument& requestArgument) {
892 if (requestArgument.lifetime == nn::Request::Argument::LifeTime::POINTER) {
893 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
894 << "Request cannot be unvalidatedConverted because it contains pointer-based memory";
895 }
896 const bool hasNoValue = requestArgument.lifetime == nn::Request::Argument::LifeTime::NO_VALUE;
897 return RequestArgument{
898 .hasNoValue = hasNoValue,
899 .location = NN_TRY(unvalidatedConvert(requestArgument.location)),
900 .dimensions = NN_TRY(toSigned(requestArgument.dimensions)),
901 };
902}
903
904nn::GeneralResult<RequestMemoryPool> unvalidatedConvert(const nn::Request::MemoryPool& memoryPool) {
905 return std::visit(
906 overloaded{
907 [](const nn::SharedMemory& memory) -> nn::GeneralResult<RequestMemoryPool> {
908 return RequestMemoryPool::make<RequestMemoryPool::Tag::pool>(
909 NN_TRY(unvalidatedConvert(memory)));
910 },
911 [](const nn::Request::MemoryDomainToken& token)
912 -> nn::GeneralResult<RequestMemoryPool> {
913 return RequestMemoryPool::make<RequestMemoryPool::Tag::token>(
914 underlyingType(token));
915 },
916 [](const nn::SharedBuffer& /*buffer*/) {
917 return (NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
918 << "Unable to make memory pool from IBuffer")
919 .
920 operator nn::GeneralResult<RequestMemoryPool>();
921 },
922 },
923 memoryPool);
924}
925
926nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
927 return Timing{
928 .timeOnDevice = NN_TRY(unvalidatedConvert(timing.timeOnDevice)),
929 .timeInDriver = NN_TRY(unvalidatedConvert(timing.timeInDriver)),
930 };
931}
932
933nn::GeneralResult<int64_t> unvalidatedConvert(const nn::Duration& duration) {
Michael Butler382d5132021-03-18 21:15:09 -0700934 if (duration < nn::Duration::zero()) {
935 return NN_ERROR() << "Unable to convert invalid (negative) duration";
Lev Proleev900c28a2021-01-26 19:40:20 +0000936 }
Michael Butler382d5132021-03-18 21:15:09 -0700937 constexpr std::chrono::nanoseconds::rep kIntMax = std::numeric_limits<int64_t>::max();
938 const auto count = duration.count();
939 return static_cast<int64_t>(std::min(count, kIntMax));
Lev Proleev900c28a2021-01-26 19:40:20 +0000940}
941
942nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalDuration& optionalDuration) {
943 if (!optionalDuration.has_value()) {
944 return kNoTiming;
945 }
946 return unvalidatedConvert(optionalDuration.value());
947}
948
949nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalTimePoint& optionalTimePoint) {
950 if (!optionalTimePoint.has_value()) {
951 return kNoTiming;
952 }
953 return unvalidatedConvert(optionalTimePoint->time_since_epoch());
954}
955
956nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvert(const nn::SyncFence& syncFence) {
957 auto duplicatedFd = NN_TRY(nn::dupFd(syncFence.getFd()));
958 return ndk::ScopedFileDescriptor(duplicatedFd.release());
959}
960
961nn::GeneralResult<ndk::ScopedFileDescriptor> unvalidatedConvertCache(
962 const nn::SharedHandle& handle) {
963 if (handle->ints.size() != 0) {
964 NN_ERROR() << "Cache handle must not contain ints";
965 }
966 if (handle->fds.size() != 1) {
967 NN_ERROR() << "Cache handle must contain exactly one fd but contains "
968 << handle->fds.size();
969 }
970 auto duplicatedFd = NN_TRY(nn::dupFd(handle->fds.front().get()));
971 return ndk::ScopedFileDescriptor(duplicatedFd.release());
972}
973
974nn::GeneralResult<std::vector<uint8_t>> convert(const nn::CacheToken& cacheToken) {
Michael Butler388bceb2021-02-03 15:15:43 -0800975 return validatedConvert(cacheToken);
Lev Proleev900c28a2021-01-26 19:40:20 +0000976}
977
978nn::GeneralResult<BufferDesc> convert(const nn::BufferDesc& bufferDesc) {
979 return validatedConvert(bufferDesc);
980}
981
982nn::GeneralResult<bool> convert(const nn::MeasureTiming& measureTiming) {
983 return validatedConvert(measureTiming);
984}
985
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800986nn::GeneralResult<Memory> convert(const nn::SharedMemory& memory) {
Lev Proleev6b6dfcd2020-11-11 18:28:50 +0000987 return validatedConvert(memory);
988}
989
990nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus) {
991 return validatedConvert(errorStatus);
992}
993
Lev Proleev900c28a2021-01-26 19:40:20 +0000994nn::GeneralResult<ExecutionPreference> convert(const nn::ExecutionPreference& executionPreference) {
995 return validatedConvert(executionPreference);
996}
997
998nn::GeneralResult<Model> convert(const nn::Model& model) {
999 return validatedConvert(model);
1000}
1001
1002nn::GeneralResult<Priority> convert(const nn::Priority& priority) {
1003 return validatedConvert(priority);
1004}
1005
1006nn::GeneralResult<Request> convert(const nn::Request& request) {
1007 return validatedConvert(request);
1008}
1009
1010nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
1011 return validatedConvert(timing);
1012}
1013
1014nn::GeneralResult<int64_t> convert(const nn::OptionalDuration& optionalDuration) {
1015 return validatedConvert(optionalDuration);
1016}
1017
1018nn::GeneralResult<int64_t> convert(const nn::OptionalTimePoint& outputShapes) {
1019 return validatedConvert(outputShapes);
1020}
1021
1022nn::GeneralResult<std::vector<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles) {
1023 return validatedConvert(bufferRoles);
1024}
1025
Lev Proleev6b6dfcd2020-11-11 18:28:50 +00001026nn::GeneralResult<std::vector<OutputShape>> convert(
1027 const std::vector<nn::OutputShape>& outputShapes) {
1028 return validatedConvert(outputShapes);
1029}
1030
Lev Proleev900c28a2021-01-26 19:40:20 +00001031nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
1032 const std::vector<nn::SharedHandle>& cacheHandles) {
1033 const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(cacheHandles)));
1034 if (version > kVersion) {
1035 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
1036 }
1037 std::vector<ndk::ScopedFileDescriptor> cacheFds;
1038 cacheFds.reserve(cacheHandles.size());
1039 for (const auto& cacheHandle : cacheHandles) {
1040 cacheFds.push_back(NN_TRY(unvalidatedConvertCache(cacheHandle)));
1041 }
1042 return cacheFds;
1043}
1044
1045nn::GeneralResult<std::vector<ndk::ScopedFileDescriptor>> convert(
1046 const std::vector<nn::SyncFence>& syncFences) {
Michael Butler388bceb2021-02-03 15:15:43 -08001047 return validatedConvert(syncFences);
Lev Proleev900c28a2021-01-26 19:40:20 +00001048}
1049
Lev Proleev6b6dfcd2020-11-11 18:28:50 +00001050nn::GeneralResult<std::vector<int32_t>> toSigned(const std::vector<uint32_t>& vec) {
1051 if (!std::all_of(vec.begin(), vec.end(),
1052 [](uint32_t v) { return v <= std::numeric_limits<int32_t>::max(); })) {
1053 return NN_ERROR() << "Vector contains a value that doesn't fit into int32_t.";
1054 }
1055 return std::vector<int32_t>(vec.begin(), vec.end());
1056}
1057
1058} // namespace aidl::android::hardware::neuralnetworks::utils