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 #define LOG_TAG "HandleImporter"
18 #include "HandleImporter.h"
19 
20 #include <gralloctypes/Gralloc4.h>
21 #include <log/log.h>
22 
23 namespace android {
24 namespace hardware {
25 namespace camera {
26 namespace common {
27 namespace V1_0 {
28 namespace helper {
29 
30 using aidl::android::hardware::graphics::common::PlaneLayout;
31 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
32 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
33 using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
34 using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
35 using MapperErrorV4 = android::hardware::graphics::mapper::V4_0::Error;
36 using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper;
37 using IMapperV4 = android::hardware::graphics::mapper::V4_0::IMapper;
38 
HandleImporter()39 HandleImporter::HandleImporter() : mInitialized(false) {}
40 
initializeLocked()41 void HandleImporter::initializeLocked() {
42     if (mInitialized) {
43         return;
44     }
45 
46     mMapperV4 = IMapperV4::getService();
47     if (mMapperV4 != nullptr) {
48         mInitialized = true;
49         return;
50     }
51 
52     mMapperV3 = IMapperV3::getService();
53     if (mMapperV3 != nullptr) {
54         mInitialized = true;
55         return;
56     }
57 
58     mMapperV2 = IMapper::getService();
59     if (mMapperV2 == nullptr) {
60         ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
61         return;
62     }
63 
64     mInitialized = true;
65     return;
66 }
67 
cleanup()68 void HandleImporter::cleanup() {
69     mMapperV4.clear();
70     mMapperV3.clear();
71     mMapperV2.clear();
72     mInitialized = false;
73 }
74 
75 template<class M, class E>
importBufferInternal(const sp<M> mapper,buffer_handle_t & handle)76 bool HandleImporter::importBufferInternal(const sp<M> mapper, buffer_handle_t& handle) {
77     E error;
78     buffer_handle_t importedHandle;
79     auto ret = mapper->importBuffer(
80         hidl_handle(handle),
81         [&](const auto& tmpError, const auto& tmpBufferHandle) {
82             error = tmpError;
83             importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
84         });
85 
86     if (!ret.isOk()) {
87         ALOGE("%s: mapper importBuffer failed: %s",
88                 __FUNCTION__, ret.description().c_str());
89         return false;
90     }
91 
92     if (error != E::NONE) {
93         return false;
94     }
95 
96     handle = importedHandle;
97     return true;
98 }
99 
100 template<class M, class E>
lockYCbCrInternal(const sp<M> mapper,buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)101 YCbCrLayout HandleImporter::lockYCbCrInternal(const sp<M> mapper, buffer_handle_t& buf,
102         uint64_t cpuUsage, const IMapper::Rect& accessRegion) {
103     hidl_handle acquireFenceHandle;
104     auto buffer = const_cast<native_handle_t*>(buf);
105     YCbCrLayout layout = {};
106 
107     typename M::Rect accessRegionCopy = {accessRegion.left, accessRegion.top,
108             accessRegion.width, accessRegion.height};
109     mapper->lockYCbCr(buffer, cpuUsage, accessRegionCopy, acquireFenceHandle,
110             [&](const auto& tmpError, const auto& tmpLayout) {
111                 if (tmpError == E::NONE) {
112                     // Member by member copy from different versions of YCbCrLayout.
113                     layout.y = tmpLayout.y;
114                     layout.cb = tmpLayout.cb;
115                     layout.cr = tmpLayout.cr;
116                     layout.yStride = tmpLayout.yStride;
117                     layout.cStride = tmpLayout.cStride;
118                     layout.chromaStep = tmpLayout.chromaStep;
119                 } else {
120                     ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
121                 }
122            });
123     return layout;
124 }
125 
getPlaneLayouts(const sp<IMapperV4> mapper,buffer_handle_t & buf)126 std::vector<PlaneLayout> getPlaneLayouts(const sp<IMapperV4> mapper, buffer_handle_t& buf) {
127     auto buffer = const_cast<native_handle_t*>(buf);
128     std::vector<PlaneLayout> planeLayouts;
129     hidl_vec<uint8_t> encodedPlaneLayouts;
130     mapper->get(buffer, gralloc4::MetadataType_PlaneLayouts,
131                 [&](const auto& tmpError, const auto& tmpEncodedPlaneLayouts) {
132                     if (tmpError == MapperErrorV4::NONE) {
133                         encodedPlaneLayouts = tmpEncodedPlaneLayouts;
134                     } else {
135                         ALOGE("%s: failed to get plane layouts %d!", __FUNCTION__, tmpError);
136                     }
137                 });
138 
139     gralloc4::decodePlaneLayouts(encodedPlaneLayouts, &planeLayouts);
140 
141     return planeLayouts;
142 }
143 
144 template <>
lockYCbCrInternal(const sp<IMapperV4> mapper,buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)145 YCbCrLayout HandleImporter::lockYCbCrInternal<IMapperV4, MapperErrorV4>(
146         const sp<IMapperV4> mapper, buffer_handle_t& buf, uint64_t cpuUsage,
147         const IMapper::Rect& accessRegion) {
148     hidl_handle acquireFenceHandle;
149     auto buffer = const_cast<native_handle_t*>(buf);
150     YCbCrLayout layout = {};
151     void* mapped = nullptr;
152 
153     typename IMapperV4::Rect accessRegionV4 = {accessRegion.left, accessRegion.top,
154                                                accessRegion.width, accessRegion.height};
155     mapper->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
156                  [&](const auto& tmpError, const auto& tmpPtr) {
157                      if (tmpError == MapperErrorV4::NONE) {
158                          mapped = tmpPtr;
159                      } else {
160                          ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
161                      }
162                  });
163 
164     if (mapped == nullptr) {
165         return layout;
166     }
167 
168     std::vector<PlaneLayout> planeLayouts = getPlaneLayouts(mapper, buf);
169     for (const auto& planeLayout : planeLayouts) {
170         for (const auto& planeLayoutComponent : planeLayout.components) {
171             const auto& type = planeLayoutComponent.type;
172 
173             if (!gralloc4::isStandardPlaneLayoutComponentType(type)) {
174                 continue;
175             }
176 
177             uint8_t* data = reinterpret_cast<uint8_t*>(mapped);
178             data += planeLayout.offsetInBytes;
179             data += planeLayoutComponent.offsetInBits / 8;
180 
181             switch (static_cast<PlaneLayoutComponentType>(type.value)) {
182                 case PlaneLayoutComponentType::Y:
183                     layout.y = data;
184                     layout.yStride = planeLayout.strideInBytes;
185                     break;
186                 case PlaneLayoutComponentType::CB:
187                     layout.cb = data;
188                     layout.cStride = planeLayout.strideInBytes;
189                     layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
190                     break;
191                 case PlaneLayoutComponentType::CR:
192                     layout.cr = data;
193                     layout.cStride = planeLayout.strideInBytes;
194                     layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
195                     break;
196                 default:
197                     break;
198             }
199         }
200     }
201 
202     return layout;
203 }
204 
205 template<class M, class E>
unlockInternal(const sp<M> mapper,buffer_handle_t & buf)206 int HandleImporter::unlockInternal(const sp<M> mapper, buffer_handle_t& buf) {
207     int releaseFence = -1;
208     auto buffer = const_cast<native_handle_t*>(buf);
209 
210     mapper->unlock(
211         buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
212             if (tmpError == E::NONE) {
213                 auto fenceHandle = tmpReleaseFence.getNativeHandle();
214                 if (fenceHandle) {
215                     if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
216                         ALOGE("%s: bad release fence numInts %d numFds %d",
217                                 __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
218                         return;
219                     }
220                     releaseFence = dup(fenceHandle->data[0]);
221                     if (releaseFence < 0) {
222                         ALOGE("%s: bad release fence FD %d",
223                                 __FUNCTION__, releaseFence);
224                     }
225                 }
226             } else {
227                 ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
228             }
229         });
230     return releaseFence;
231 }
232 
233 // In IComposer, any buffer_handle_t is owned by the caller and we need to
234 // make a clone for hwcomposer2.  We also need to translate empty handle
235 // to nullptr.  This function does that, in-place.
importBuffer(buffer_handle_t & handle)236 bool HandleImporter::importBuffer(buffer_handle_t& handle) {
237     if (!handle->numFds && !handle->numInts) {
238         handle = nullptr;
239         return true;
240     }
241 
242     Mutex::Autolock lock(mLock);
243     if (!mInitialized) {
244         initializeLocked();
245     }
246 
247     if (mMapperV4 != nullptr) {
248         return importBufferInternal<IMapperV4, MapperErrorV4>(mMapperV4, handle);
249     }
250 
251     if (mMapperV3 != nullptr) {
252         return importBufferInternal<IMapperV3, MapperErrorV3>(mMapperV3, handle);
253     }
254 
255     if (mMapperV2 != nullptr) {
256         return importBufferInternal<IMapper, MapperErrorV2>(mMapperV2, handle);
257     }
258 
259     ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
260     return false;
261 }
262 
freeBuffer(buffer_handle_t handle)263 void HandleImporter::freeBuffer(buffer_handle_t handle) {
264     if (!handle) {
265         return;
266     }
267 
268     Mutex::Autolock lock(mLock);
269     if (!mInitialized) {
270         initializeLocked();
271     }
272 
273     if (mMapperV4 != nullptr) {
274         auto ret = mMapperV4->freeBuffer(const_cast<native_handle_t*>(handle));
275         if (!ret.isOk()) {
276             ALOGE("%s: mapper freeBuffer failed: %s", __FUNCTION__, ret.description().c_str());
277         }
278     } else if (mMapperV3 != nullptr) {
279         auto ret = mMapperV3->freeBuffer(const_cast<native_handle_t*>(handle));
280         if (!ret.isOk()) {
281             ALOGE("%s: mapper freeBuffer failed: %s",
282                     __FUNCTION__, ret.description().c_str());
283         }
284     } else {
285         auto ret = mMapperV2->freeBuffer(const_cast<native_handle_t*>(handle));
286         if (!ret.isOk()) {
287             ALOGE("%s: mapper freeBuffer failed: %s",
288                     __FUNCTION__, ret.description().c_str());
289         }
290     }
291 }
292 
importFence(const native_handle_t * handle,int & fd) const293 bool HandleImporter::importFence(const native_handle_t* handle, int& fd) const {
294     if (handle == nullptr || handle->numFds == 0) {
295         fd = -1;
296     } else if (handle->numFds == 1) {
297         fd = dup(handle->data[0]);
298         if (fd < 0) {
299             ALOGE("failed to dup fence fd %d", handle->data[0]);
300             return false;
301         }
302     } else {
303         ALOGE("invalid fence handle with %d file descriptors",
304                 handle->numFds);
305         return false;
306     }
307 
308     return true;
309 }
310 
closeFence(int fd) const311 void HandleImporter::closeFence(int fd) const {
312     if (fd >= 0) {
313         close(fd);
314     }
315 }
316 
lock(buffer_handle_t & buf,uint64_t cpuUsage,size_t size)317 void* HandleImporter::lock(
318         buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
319     IMapper::Rect accessRegion{0, 0, static_cast<int>(size), 1};
320     return lock(buf, cpuUsage, accessRegion);
321 }
322 
lock(buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)323 void* HandleImporter::lock(buffer_handle_t& buf, uint64_t cpuUsage,
324                            const IMapper::Rect& accessRegion) {
325     Mutex::Autolock lock(mLock);
326 
327     if (!mInitialized) {
328         initializeLocked();
329     }
330 
331     void* ret = nullptr;
332 
333     if (mMapperV4 == nullptr && mMapperV3 == nullptr && mMapperV2 == nullptr) {
334         ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
335         return ret;
336     }
337 
338     hidl_handle acquireFenceHandle;
339     auto buffer = const_cast<native_handle_t*>(buf);
340     if (mMapperV4 != nullptr) {
341         IMapperV4::Rect accessRegionV4{accessRegion.left, accessRegion.top, accessRegion.width,
342                                        accessRegion.height};
343 
344         mMapperV4->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
345                         [&](const auto& tmpError, const auto& tmpPtr) {
346                             if (tmpError == MapperErrorV4::NONE) {
347                                 ret = tmpPtr;
348                             } else {
349                                 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
350                             }
351                         });
352     } else if (mMapperV3 != nullptr) {
353         IMapperV3::Rect accessRegionV3{accessRegion.left, accessRegion.top, accessRegion.width,
354                                        accessRegion.height};
355 
356         mMapperV3->lock(buffer, cpuUsage, accessRegionV3, acquireFenceHandle,
357                         [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
358                             const auto& /*bytesPerStride*/) {
359                             if (tmpError == MapperErrorV3::NONE) {
360                                 ret = tmpPtr;
361                             } else {
362                                 ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
363                             }
364                         });
365     } else {
366         mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
367                 [&](const auto& tmpError, const auto& tmpPtr) {
368                     if (tmpError == MapperErrorV2::NONE) {
369                         ret = tmpPtr;
370                     } else {
371                         ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
372                     }
373                });
374     }
375 
376     ALOGV("%s: ptr %p accessRegion.top: %d accessRegion.left: %d accessRegion.width: %d "
377           "accessRegion.height: %d",
378           __FUNCTION__, ret, accessRegion.top, accessRegion.left, accessRegion.width,
379           accessRegion.height);
380     return ret;
381 }
382 
lockYCbCr(buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)383 YCbCrLayout HandleImporter::lockYCbCr(
384         buffer_handle_t& buf, uint64_t cpuUsage,
385         const IMapper::Rect& accessRegion) {
386     Mutex::Autolock lock(mLock);
387 
388     if (!mInitialized) {
389         initializeLocked();
390     }
391 
392     if (mMapperV4 != nullptr) {
393         return lockYCbCrInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf, cpuUsage, accessRegion);
394     }
395 
396     if (mMapperV3 != nullptr) {
397         return lockYCbCrInternal<IMapperV3, MapperErrorV3>(
398                 mMapperV3, buf, cpuUsage, accessRegion);
399     }
400 
401     if (mMapperV2 != nullptr) {
402         return lockYCbCrInternal<IMapper, MapperErrorV2>(
403                 mMapperV2, buf, cpuUsage, accessRegion);
404     }
405 
406     ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
407     return {};
408 }
409 
getMonoPlanarStrideBytes(buffer_handle_t & buf,uint32_t * stride)410 status_t HandleImporter::getMonoPlanarStrideBytes(buffer_handle_t &buf, uint32_t *stride /*out*/) {
411     if (stride == nullptr) {
412         return BAD_VALUE;
413     }
414 
415     Mutex::Autolock lock(mLock);
416 
417     if (!mInitialized) {
418         initializeLocked();
419     }
420 
421     if (mMapperV4 != nullptr) {
422         std::vector<PlaneLayout> planeLayouts = getPlaneLayouts(mMapperV4, buf);
423         if (planeLayouts.size() != 1) {
424             ALOGE("%s: Unexpected number of planes %zu!",  __FUNCTION__, planeLayouts.size());
425             return BAD_VALUE;
426         }
427 
428         *stride = planeLayouts[0].strideInBytes;
429     } else {
430         ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
431         return NO_INIT;
432     }
433 
434     return OK;
435 }
436 
unlock(buffer_handle_t & buf)437 int HandleImporter::unlock(buffer_handle_t& buf) {
438     if (mMapperV4 != nullptr) {
439         return unlockInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf);
440     }
441     if (mMapperV3 != nullptr) {
442         return unlockInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf);
443     }
444     if (mMapperV2 != nullptr) {
445         return unlockInternal<IMapper, MapperErrorV2>(mMapperV2, buf);
446     }
447 
448     ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
449     return -1;
450 }
451 
452 } // namespace helper
453 } // namespace V1_0
454 } // namespace common
455 } // namespace camera
456 } // namespace hardware
457 } // namespace android
458