1 /*
2 * Copyright (C) 2019 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 #ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
18 #define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
19
20 #include <android-base/logging.h>
21 #include <android/hardware/neuralnetworks/1.0/types.h>
22 #include <android/hardware_buffer.h>
23 #include <android/hidl/memory/1.0/IMemory.h>
24 #include <gtest/gtest.h>
25 #include <algorithm>
26 #include <iosfwd>
27 #include <string>
28 #include <utility>
29 #include <vector>
30 #include "TestHarness.h"
31
32 namespace android::hardware::neuralnetworks {
33
34 // Convenience class to manage the lifetime of memory resources.
35 class TestMemoryBase {
36 DISALLOW_COPY_AND_ASSIGN(TestMemoryBase);
37
38 public:
39 TestMemoryBase() = default;
40 virtual ~TestMemoryBase() = default;
getPointer()41 uint8_t* getPointer() const { return mPtr; }
getHidlMemory()42 hidl_memory getHidlMemory() const { return mHidlMemory; }
43
44 protected:
45 uint8_t* mPtr = nullptr;
46 hidl_memory mHidlMemory;
47 bool mIsValid = false;
48 };
49
50 class TestAshmem : public TestMemoryBase {
51 public:
52 static std::unique_ptr<TestAshmem> create(uint32_t size);
53
54 // Prefer TestAshmem::create.
55 // The constructor calls initialize, which constructs the memory resources. This is a workaround
56 // that gtest macros cannot be used directly in a constructor.
TestAshmem(uint32_t size)57 TestAshmem(uint32_t size) { initialize(size); }
58
59 private:
60 void initialize(uint32_t size);
61 sp<hidl::memory::V1_0::IMemory> mMappedMemory;
62 };
63
64 class TestBlobAHWB : public TestMemoryBase {
65 public:
66 static std::unique_ptr<TestBlobAHWB> create(uint32_t size);
67
68 // Prefer TestBlobAHWB::create.
69 // The constructor calls initialize, which constructs the memory resources. This is a
70 // workaround that gtest macros cannot be used directly in a constructor.
TestBlobAHWB(uint32_t size)71 TestBlobAHWB(uint32_t size) { initialize(size); }
72 ~TestBlobAHWB();
73
74 private:
75 void initialize(uint32_t size);
76 AHardwareBuffer* mAhwb = nullptr;
77 };
78
79 enum class MemoryType { ASHMEM, BLOB_AHWB, DEVICE };
80
81 // Manages the lifetime of memory resources used in an execution.
82 class ExecutionContext {
83 DISALLOW_COPY_AND_ASSIGN(ExecutionContext);
84
85 public:
86 static constexpr uint32_t kInputPoolIndex = 0;
87 static constexpr uint32_t kOutputPoolIndex = 1;
88
89 ExecutionContext() = default;
90
91 // Create HIDL Request from the TestModel struct.
92 V1_0::Request createRequest(const test_helper::TestModel& testModel,
93 MemoryType memoryType = MemoryType::ASHMEM);
94
95 // After execution, copy out output results from the output memory pool.
96 std::vector<test_helper::TestBuffer> getOutputBuffers(const V1_0::Request& request) const;
97
98 private:
99 std::unique_ptr<TestMemoryBase> mInputMemory, mOutputMemory;
100 };
101
102 // Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
103 // so this is efficiently accomplished by moving the element to the end and
104 // resizing the hidl_vec to one less.
105 template <typename Type>
hidl_vec_removeAt(hidl_vec<Type> * vec,uint32_t index)106 inline void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
107 CHECK(vec != nullptr);
108 std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
109 vec->resize(vec->size() - 1);
110 }
111
112 // Assumes there is exactly one instance of the value in the vector.
113 template <typename Type>
hidl_vec_remove(hidl_vec<Type> * vec,const Type & val)114 inline void hidl_vec_remove(hidl_vec<Type>* vec, const Type& val) {
115 CHECK(vec != nullptr);
116 auto where = std::find(vec->begin(), vec->end(), val);
117 ASSERT_NE(where, vec->end());
118 hidl_vec_removeAt(vec, where - vec->begin());
119 }
120
121 template <typename Type>
hidl_vec_push_back(hidl_vec<Type> * vec,const Type & value)122 inline uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
123 CHECK(vec != nullptr);
124 const uint32_t index = vec->size();
125 vec->resize(index + 1);
126 (*vec)[index] = value;
127 return index;
128 }
129
130 // Returns the amount of space needed to store a value of the specified type.
131 //
132 // Aborts if the specified type is an extension type or OEM type.
133 uint32_t sizeOfData(V1_0::OperandType type);
134
135 // Returns the amount of space needed to store a value of the dimensions and
136 // type of this operand. For a non-extension, non-OEM tensor with unspecified
137 // rank or at least one unspecified dimension, returns zero.
138 //
139 // Aborts if the specified type is an extension type or OEM type.
140 uint32_t sizeOfData(const V1_0::Operand& operand);
141
142 template <typename Type>
143 using Named = std::pair<std::string, Type>;
144
145 template <typename Type>
getName(const Named<Type> & namedData)146 const std::string& getName(const Named<Type>& namedData) {
147 return namedData.first;
148 }
149
150 template <typename Type>
getData(const Named<Type> & namedData)151 const Type& getData(const Named<Type>& namedData) {
152 return namedData.second;
153 }
154
155 std::string gtestCompliantName(std::string name);
156
157 } // namespace android::hardware::neuralnetworks
158
159 namespace android::hardware::neuralnetworks::V1_0 {
160
161 // pretty-print values for error messages
162 ::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
163 ::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
164
165 } // namespace android::hardware::neuralnetworks::V1_0
166
167 #endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
168