1 /*
2 * Copyright (C) 2017 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 <mapper-vts/2.0/MapperVts.h>
18
19 namespace android {
20 namespace hardware {
21 namespace graphics {
22 namespace mapper {
23 namespace V2_0 {
24 namespace vts {
25
Gralloc(const std::string & allocatorServiceName,const std::string & mapperServiceName)26 Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
27 init(allocatorServiceName, mapperServiceName);
28 }
29
init(const std::string & allocatorServiceName,const std::string & mapperServiceName)30 void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
31 mAllocator = IAllocator::getService(allocatorServiceName);
32 ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
33
34 mMapper = IMapper::getService(mapperServiceName);
35 ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
36 ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
37 }
38
~Gralloc()39 Gralloc::~Gralloc() {
40 for (auto bufferHandle : mClonedBuffers) {
41 auto buffer = const_cast<native_handle_t*>(bufferHandle);
42 native_handle_close(buffer);
43 native_handle_delete(buffer);
44 }
45 mClonedBuffers.clear();
46
47 for (auto bufferHandle : mImportedBuffers) {
48 auto buffer = const_cast<native_handle_t*>(bufferHandle);
49 EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) << "failed to free buffer " << buffer;
50 }
51 mImportedBuffers.clear();
52 }
53
getAllocator() const54 sp<IAllocator> Gralloc::getAllocator() const {
55 return mAllocator;
56 }
57
dumpDebugInfo()58 std::string Gralloc::dumpDebugInfo() {
59 std::string debugInfo;
60 mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
61
62 return debugInfo;
63 }
64
cloneBuffer(const hidl_handle & rawHandle)65 const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
66 const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
67 EXPECT_NE(nullptr, bufferHandle);
68
69 if (bufferHandle) {
70 mClonedBuffers.insert(bufferHandle);
71 }
72
73 return bufferHandle;
74 }
75
allocate(const BufferDescriptor & descriptor,uint32_t count,bool import,uint32_t * outStride)76 std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
77 uint32_t count, bool import,
78 uint32_t* outStride) {
79 std::vector<const native_handle_t*> bufferHandles;
80 bufferHandles.reserve(count);
81 mAllocator->allocate(
82 descriptor, count,
83 [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
84 ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
85 ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
86
87 for (uint32_t i = 0; i < count; i++) {
88 if (import) {
89 ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(importBuffer(tmpBuffers[i])));
90 } else {
91 ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
92 }
93 }
94
95 if (outStride) {
96 *outStride = tmpStride;
97 }
98 });
99
100 if (::testing::Test::HasFatalFailure()) {
101 bufferHandles.clear();
102 }
103
104 return bufferHandles;
105 }
106
allocate(const IMapper::BufferDescriptorInfo & descriptorInfo,bool import,uint32_t * outStride)107 const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
108 bool import, uint32_t* outStride) {
109 BufferDescriptor descriptor = createDescriptor(descriptorInfo);
110 if (::testing::Test::HasFatalFailure()) {
111 return nullptr;
112 }
113
114 auto buffers = allocate(descriptor, 1, import, outStride);
115 if (::testing::Test::HasFatalFailure()) {
116 return nullptr;
117 }
118
119 return buffers[0];
120 }
121
getMapper() const122 sp<IMapper> Gralloc::getMapper() const {
123 return mMapper;
124 }
125
createDescriptor(const IMapper::BufferDescriptorInfo & descriptorInfo)126 BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
127 BufferDescriptor descriptor;
128 mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
129 ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
130 descriptor = tmpDescriptor;
131 });
132
133 return descriptor;
134 }
135
importBuffer(const hidl_handle & rawHandle)136 const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
137 const native_handle_t* bufferHandle = nullptr;
138 mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
139 ASSERT_EQ(Error::NONE, tmpError)
140 << "failed to import buffer %p" << rawHandle.getNativeHandle();
141 bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
142 });
143
144 if (bufferHandle) {
145 mImportedBuffers.insert(bufferHandle);
146 }
147
148 return bufferHandle;
149 }
150
freeBuffer(const native_handle_t * bufferHandle)151 void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
152 auto buffer = const_cast<native_handle_t*>(bufferHandle);
153
154 if (mImportedBuffers.erase(bufferHandle)) {
155 Error error = mMapper->freeBuffer(buffer);
156 ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer;
157 } else {
158 mClonedBuffers.erase(bufferHandle);
159 native_handle_close(buffer);
160 native_handle_delete(buffer);
161 }
162 }
163
lock(const native_handle_t * bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,int acquireFence)164 void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
165 const IMapper::Rect& accessRegion, int acquireFence) {
166 auto buffer = const_cast<native_handle_t*>(bufferHandle);
167
168 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
169 hidl_handle acquireFenceHandle;
170 if (acquireFence >= 0) {
171 auto h = native_handle_init(acquireFenceStorage, 1, 0);
172 h->data[0] = acquireFence;
173 acquireFenceHandle = h;
174 }
175
176 void* data = nullptr;
177 mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
178 [&](const auto& tmpError, const auto& tmpData) {
179 ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
180 data = tmpData;
181 });
182
183 if (acquireFence >= 0) {
184 close(acquireFence);
185 }
186
187 return data;
188 }
189
lockYCbCr(const native_handle_t * bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,int acquireFence)190 YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
191 const IMapper::Rect& accessRegion, int acquireFence) {
192 auto buffer = const_cast<native_handle_t*>(bufferHandle);
193
194 NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
195 hidl_handle acquireFenceHandle;
196 if (acquireFence >= 0) {
197 auto h = native_handle_init(acquireFenceStorage, 1, 0);
198 h->data[0] = acquireFence;
199 acquireFenceHandle = h;
200 }
201
202 YCbCrLayout layout = {};
203 mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
204 [&](const auto& tmpError, const auto& tmpLayout) {
205 ASSERT_EQ(Error::NONE, tmpError)
206 << "failed to lockYCbCr buffer " << buffer;
207 layout = tmpLayout;
208 });
209
210 if (acquireFence >= 0) {
211 close(acquireFence);
212 }
213
214 return layout;
215 }
216
unlock(const native_handle_t * bufferHandle)217 int Gralloc::unlock(const native_handle_t* bufferHandle) {
218 auto buffer = const_cast<native_handle_t*>(bufferHandle);
219
220 int releaseFence = -1;
221 mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
222 ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer " << buffer;
223
224 auto fenceHandle = tmpReleaseFence.getNativeHandle();
225 if (fenceHandle) {
226 ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
227 if (fenceHandle->numFds == 1) {
228 releaseFence = dup(fenceHandle->data[0]);
229 ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
230 } else {
231 ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
232 }
233 }
234 });
235
236 return releaseFence;
237 }
238
239 } // namespace vts
240 } // namespace V2_0
241 } // namespace mapper
242 } // namespace graphics
243 } // namespace hardware
244 } // namespace android
245