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