1 /*
2  * Copyright 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 #include <gralloctypes/Gralloc4.h>
18 #include <mapper-vts/4.0/MapperVts.h>
19 
20 namespace android {
21 namespace hardware {
22 namespace graphics {
23 namespace mapper {
24 namespace V4_0 {
25 namespace vts {
26 
Gralloc(const std::string & allocatorServiceName,const std::string & mapperServiceName,bool errOnFailure)27 Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName,
28                  bool errOnFailure) {
29     if (errOnFailure) {
30         init(allocatorServiceName, mapperServiceName);
31     } else {
32         initNoErr(allocatorServiceName, mapperServiceName);
33     }
34 }
35 
init(const std::string & allocatorServiceName,const std::string & mapperServiceName)36 void Gralloc::init(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
37     mAllocator = IAllocator::getService(allocatorServiceName);
38     ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
39 
40     mMapper = IMapper::getService(mapperServiceName);
41     ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
42     ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
43 }
44 
initNoErr(const std::string & allocatorServiceName,const std::string & mapperServiceName)45 void Gralloc::initNoErr(const std::string& allocatorServiceName,
46                         const std::string& mapperServiceName) {
47     mAllocator = IAllocator::getService(allocatorServiceName);
48 
49     mMapper = IMapper::getService(mapperServiceName);
50     if (mMapper.get()) {
51         ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
52     }
53 }
54 
~Gralloc()55 Gralloc::~Gralloc() {
56     for (auto bufferHandle : mClonedBuffers) {
57         auto buffer = const_cast<native_handle_t*>(bufferHandle);
58         native_handle_close(buffer);
59         native_handle_delete(buffer);
60     }
61     mClonedBuffers.clear();
62 
63     for (auto bufferHandle : mImportedBuffers) {
64         auto buffer = const_cast<native_handle_t*>(bufferHandle);
65         EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) << "failed to free buffer " << buffer;
66     }
67     mImportedBuffers.clear();
68 }
69 
getAllocator() const70 sp<IAllocator> Gralloc::getAllocator() const {
71     return mAllocator;
72 }
73 
cloneBuffer(const hidl_handle & rawHandle,enum Tolerance)74 const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle,
75                                             enum Tolerance /*tolerance*/) {
76     const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
77     EXPECT_NE(nullptr, bufferHandle);
78 
79     if (bufferHandle) {
80         mClonedBuffers.insert(bufferHandle);
81     }
82 
83     return bufferHandle;
84 }
85 
allocate(const BufferDescriptor & descriptor,uint32_t count,bool import,enum Tolerance tolerance,uint32_t * outStride)86 std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
87                                                       uint32_t count, bool import,
88                                                       enum Tolerance tolerance,
89                                                       uint32_t* outStride) {
90     std::vector<const native_handle_t*> bufferHandles;
91     bufferHandles.reserve(count);
92     mAllocator->allocate(descriptor, count,
93                          [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
94                              if (canTolerate(tolerance, tmpError)) {
95                                  return;
96                              }
97 
98                              ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
99                              ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
100 
101                              for (uint32_t i = 0; i < count; i++) {
102                                  const native_handle_t* bufferHandle = nullptr;
103                                  if (import) {
104                                      ASSERT_NO_FATAL_FAILURE(
105                                              bufferHandle = importBuffer(tmpBuffers[i], tolerance));
106                                  } else {
107                                      ASSERT_NO_FATAL_FAILURE(
108                                              bufferHandle = cloneBuffer(tmpBuffers[i], tolerance));
109                                  }
110                                  if (bufferHandle) {
111                                      bufferHandles.push_back(bufferHandle);
112                                  }
113                              }
114 
115                              if (outStride) {
116                                  *outStride = tmpStride;
117                              }
118                          });
119 
120     if (::testing::Test::HasFatalFailure()) {
121         bufferHandles.clear();
122     }
123 
124     return bufferHandles;
125 }
126 
allocate(const IMapper::BufferDescriptorInfo & descriptorInfo,bool import,enum Tolerance tolerance,uint32_t * outStride)127 const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
128                                          bool import, enum Tolerance tolerance,
129                                          uint32_t* outStride) {
130     BufferDescriptor descriptor = createDescriptor(descriptorInfo);
131     if (::testing::Test::HasFatalFailure()) {
132         return nullptr;
133     }
134 
135     auto buffers = allocate(descriptor, 1, import, tolerance, outStride);
136     if (::testing::Test::HasFatalFailure()) {
137         return nullptr;
138     }
139 
140     if (buffers.size() != 1) {
141         return nullptr;
142     }
143     return buffers[0];
144 }
145 
getMapper() const146 sp<IMapper> Gralloc::getMapper() const {
147     return mMapper;
148 }
149 
createDescriptor(const IMapper::BufferDescriptorInfo & descriptorInfo)150 BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
151     BufferDescriptor descriptor;
152     mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
153         ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
154         descriptor = tmpDescriptor;
155     });
156 
157     return descriptor;
158 }
159 
importBuffer(const hidl_handle & rawHandle,enum Tolerance tolerance)160 const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle,
161                                              enum Tolerance tolerance) {
162     const native_handle_t* bufferHandle = nullptr;
163     mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
164         if (!canTolerate(tolerance, tmpError)) {
165             ASSERT_EQ(Error::NONE, tmpError)
166                     << "failed to import buffer %p" << rawHandle.getNativeHandle();
167         }
168         bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
169     });
170 
171     if (bufferHandle) {
172         mImportedBuffers.insert(bufferHandle);
173     }
174 
175     return bufferHandle;
176 }
177 
freeBuffer(const native_handle_t * bufferHandle)178 void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
179     if (bufferHandle == nullptr) {
180         return;
181     }
182 
183     auto buffer = const_cast<native_handle_t*>(bufferHandle);
184 
185     if (mImportedBuffers.erase(bufferHandle)) {
186         Error error = mMapper->freeBuffer(buffer);
187         ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer;
188     } else {
189         mClonedBuffers.erase(bufferHandle);
190         native_handle_close(buffer);
191         native_handle_delete(buffer);
192     }
193 }
194 
lock(const native_handle_t * bufferHandle,uint64_t cpuUsage,const IMapper::Rect & accessRegion,int acquireFence)195 void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
196                     const IMapper::Rect& accessRegion, int acquireFence) {
197     auto buffer = const_cast<native_handle_t*>(bufferHandle);
198 
199     NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
200     hidl_handle acquireFenceHandle;
201     if (acquireFence >= 0) {
202         auto h = native_handle_init(acquireFenceStorage, 1, 0);
203         h->data[0] = acquireFence;
204         acquireFenceHandle = h;
205     }
206 
207     void* data = nullptr;
208     mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
209                   [&](const auto& tmpError, const auto& tmpData) {
210                       ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
211                       data = tmpData;
212                   });
213 
214     if (acquireFence >= 0) {
215         close(acquireFence);
216     }
217 
218     return data;
219 }
220 
unlock(const native_handle_t * bufferHandle)221 int Gralloc::unlock(const native_handle_t* bufferHandle) {
222     auto buffer = const_cast<native_handle_t*>(bufferHandle);
223 
224     int releaseFence = -1;
225     mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
226         ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer " << buffer;
227 
228         auto fenceHandle = tmpReleaseFence.getNativeHandle();
229         if (fenceHandle) {
230             ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
231             if (fenceHandle->numFds == 1) {
232                 releaseFence = dup(fenceHandle->data[0]);
233                 ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
234             } else {
235                 ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
236             }
237         }
238     });
239 
240     return releaseFence;
241 }
242 
flushLockedBuffer(const native_handle_t * bufferHandle)243 int Gralloc::flushLockedBuffer(const native_handle_t* bufferHandle) {
244     auto buffer = const_cast<native_handle_t*>(bufferHandle);
245 
246     int releaseFence = -1;
247     mMapper->flushLockedBuffer(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
248         ASSERT_EQ(Error::NONE, tmpError) << "failed to flush locked buffer " << buffer;
249 
250         auto fenceHandle = tmpReleaseFence.getNativeHandle();
251         if (fenceHandle) {
252             ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle " << fenceHandle;
253             if (fenceHandle->numFds == 1) {
254                 releaseFence = dup(fenceHandle->data[0]);
255                 ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
256             } else {
257                 ASSERT_EQ(0, fenceHandle->numFds) << " invalid fence handle " << fenceHandle;
258             }
259         }
260     });
261 
262     return releaseFence;
263 }
264 
rereadLockedBuffer(const native_handle_t * bufferHandle)265 void Gralloc::rereadLockedBuffer(const native_handle_t* bufferHandle) {
266     auto buffer = const_cast<native_handle_t*>(bufferHandle);
267 
268     ASSERT_EQ(Error::NONE, mMapper->rereadLockedBuffer(buffer));
269 }
270 
validateBufferSize(const native_handle_t * bufferHandle,const IMapper::BufferDescriptorInfo & descriptorInfo,uint32_t stride)271 bool Gralloc::validateBufferSize(const native_handle_t* bufferHandle,
272                                  const IMapper::BufferDescriptorInfo& descriptorInfo,
273                                  uint32_t stride) {
274     auto buffer = const_cast<native_handle_t*>(bufferHandle);
275 
276     Error error = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
277     return error == Error::NONE;
278 }
279 
getTransportSize(const native_handle_t * bufferHandle,uint32_t * outNumFds,uint32_t * outNumInts)280 void Gralloc::getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
281                                uint32_t* outNumInts) {
282     auto buffer = const_cast<native_handle_t*>(bufferHandle);
283 
284     *outNumFds = 0;
285     *outNumInts = 0;
286     mMapper->getTransportSize(buffer, [&](const auto& tmpError, const auto& tmpNumFds,
287                                           const auto& tmpNumInts) {
288         ASSERT_EQ(Error::NONE, tmpError) << "failed to get transport size";
289         ASSERT_GE(bufferHandle->numFds, int(tmpNumFds)) << "invalid numFds " << tmpNumFds;
290         ASSERT_GE(bufferHandle->numInts, int(tmpNumInts)) << "invalid numInts " << tmpNumInts;
291 
292         *outNumFds = tmpNumFds;
293         *outNumInts = tmpNumInts;
294     });
295 }
296 
isSupported(const IMapper::BufferDescriptorInfo & descriptorInfo)297 bool Gralloc::isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo) {
298     bool supported = false;
299     mMapper->isSupported(descriptorInfo, [&](const auto& tmpError, const auto& tmpSupported) {
300         ASSERT_EQ(Error::NONE, tmpError) << "failed to check is supported";
301         supported = tmpSupported;
302     });
303     return supported;
304 }
305 
get(const native_handle_t * bufferHandle,const IMapper::MetadataType & metadataType,hidl_vec<uint8_t> * outVec)306 Error Gralloc::get(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType,
307                    hidl_vec<uint8_t>* outVec) {
308     Error err;
309     mMapper->get(const_cast<native_handle_t*>(bufferHandle), metadataType,
310                  [&](const auto& tmpError, const hidl_vec<uint8_t>& tmpVec) {
311                      err = tmpError;
312                      *outVec = tmpVec;
313                  });
314     return err;
315 }
316 
set(const native_handle_t * bufferHandle,const IMapper::MetadataType & metadataType,const hidl_vec<uint8_t> & vec)317 Error Gralloc::set(const native_handle_t* bufferHandle, const IMapper::MetadataType& metadataType,
318                    const hidl_vec<uint8_t>& vec) {
319     return mMapper->set(const_cast<native_handle_t*>(bufferHandle), metadataType, vec);
320 }
321 
getFromBufferDescriptorInfo(const IMapper::BufferDescriptorInfo & descriptorInfo,const IMapper::MetadataType & metadataType,hidl_vec<uint8_t> * outVec)322 Error Gralloc::getFromBufferDescriptorInfo(const IMapper::BufferDescriptorInfo& descriptorInfo,
323                                            const IMapper::MetadataType& metadataType,
324                                            hidl_vec<uint8_t>* outVec) {
325     Error err;
326     mMapper->getFromBufferDescriptorInfo(
327             descriptorInfo, metadataType,
328             [&](const auto& tmpError, const hidl_vec<uint8_t>& tmpVec) {
329                 err = tmpError;
330                 *outVec = tmpVec;
331             });
332     return err;
333 }
334 
getReservedRegion(const native_handle_t * bufferHandle,void ** outReservedRegion,uint64_t * outReservedSize)335 Error Gralloc::getReservedRegion(const native_handle_t* bufferHandle, void** outReservedRegion,
336                                  uint64_t* outReservedSize) {
337     Error err;
338     mMapper->getReservedRegion(
339             const_cast<native_handle_t*>(bufferHandle),
340             [&](const auto& tmpError, const auto& tmpReservedRegion, const auto& tmpReservedSize) {
341                 err = tmpError;
342                 *outReservedRegion = tmpReservedRegion;
343                 *outReservedSize = tmpReservedSize;
344             });
345     return err;
346 }
347 
348 }  // namespace vts
349 }  // namespace V4_0
350 }  // namespace mapper
351 }  // namespace graphics
352 }  // namespace hardware
353 }  // namespace android
354