1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "Buffer.h"
18 
19 #include <android-base/logging.h>
20 #include <android/hardware/neuralnetworks/1.3/IBuffer.h>
21 #include <android/hardware/neuralnetworks/1.3/types.h>
22 #include <nnapi/IBuffer.h>
23 #include <nnapi/TypeUtils.h>
24 #include <nnapi/Types.h>
25 #include <nnapi/hal/1.3/Utils.h>
26 #include <memory>
27 
28 // See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
29 // lifetimes across processes and for protecting asynchronous calls across HIDL.
30 
31 namespace android::hardware::neuralnetworks::adapter {
32 namespace {
33 
34 template <typename Type>
convertInput(const Type & object)35 auto convertInput(const Type& object) -> decltype(nn::convert(std::declval<Type>())) {
36     auto result = nn::convert(object);
37     if (!result.has_value()) {
38         result.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
39     }
40     return result;
41 }
42 
copyTo(const nn::SharedBuffer & buffer,const hidl_memory & dst)43 nn::GeneralResult<void> copyTo(const nn::SharedBuffer& buffer, const hidl_memory& dst) {
44     const auto memory = NN_TRY(convertInput(dst));
45     NN_TRY(buffer->copyTo(memory));
46     return {};
47 }
48 
copyFrom(const nn::SharedBuffer & buffer,const hidl_memory & src,const hidl_vec<uint32_t> & dimensions)49 nn::GeneralResult<void> copyFrom(const nn::SharedBuffer& buffer, const hidl_memory& src,
50                                  const hidl_vec<uint32_t>& dimensions) {
51     const auto memory = NN_TRY(convertInput(src));
52     NN_TRY(buffer->copyFrom(memory, dimensions));
53     return {};
54 }
55 
56 }  // namespace
57 
Buffer(nn::SharedBuffer buffer)58 Buffer::Buffer(nn::SharedBuffer buffer) : kBuffer(std::move(buffer)) {
59     CHECK(kBuffer != nullptr);
60 }
61 
copyTo(const hidl_memory & dst)62 Return<V1_3::ErrorStatus> Buffer::copyTo(const hidl_memory& dst) {
63     auto result = adapter::copyTo(kBuffer, dst);
64     if (!result.has_value()) {
65         const auto [message, code] = std::move(result).error();
66         LOG(ERROR) << "adapter::Buffer::copyTo failed with " << code << ": " << message;
67         return V1_3::utils::convert(code).value();
68     }
69     return V1_3::ErrorStatus::NONE;
70 }
71 
copyFrom(const hidl_memory & src,const hidl_vec<uint32_t> & dimensions)72 Return<V1_3::ErrorStatus> Buffer::copyFrom(const hidl_memory& src,
73                                            const hidl_vec<uint32_t>& dimensions) {
74     auto result = adapter::copyFrom(kBuffer, src, dimensions);
75     if (!result.has_value()) {
76         const auto [message, code] = std::move(result).error();
77         LOG(ERROR) << "adapter::Buffer::copyFrom failed with " << code << ": " << message;
78         return V1_3::utils::convert(code).value();
79     }
80     return V1_3::ErrorStatus::NONE;
81 }
82 
83 }  // namespace android::hardware::neuralnetworks::adapter
84