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