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 #include <log/log.h>
20 
21 namespace android {
22 namespace hardware {
23 namespace camera {
24 namespace common {
25 namespace V1_0 {
26 namespace helper {
27 
28 using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
29 using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
30 using IMapperV3 = android::hardware::graphics::mapper::V3_0::IMapper;
31 
HandleImporter()32 HandleImporter::HandleImporter() : mInitialized(false) {}
33 
initializeLocked()34 void HandleImporter::initializeLocked() {
35     if (mInitialized) {
36         return;
37     }
38 
39     mMapperV3 = IMapperV3::getService();
40     if (mMapperV3 != nullptr) {
41         mInitialized = true;
42         return;
43     }
44 
45     mMapperV2 = IMapper::getService();
46     if (mMapperV2 == nullptr) {
47         ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
48         return;
49     }
50 
51     mInitialized = true;
52     return;
53 }
54 
cleanup()55 void HandleImporter::cleanup() {
56     mMapperV3.clear();
57     mMapperV2.clear();
58     mInitialized = false;
59 }
60 
61 template<class M, class E>
importBufferInternal(const sp<M> mapper,buffer_handle_t & handle)62 bool HandleImporter::importBufferInternal(const sp<M> mapper, buffer_handle_t& handle) {
63     E error;
64     buffer_handle_t importedHandle;
65     auto ret = mapper->importBuffer(
66         hidl_handle(handle),
67         [&](const auto& tmpError, const auto& tmpBufferHandle) {
68             error = tmpError;
69             importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
70         });
71 
72     if (!ret.isOk()) {
73         ALOGE("%s: mapper importBuffer failed: %s",
74                 __FUNCTION__, ret.description().c_str());
75         return false;
76     }
77 
78     if (error != E::NONE) {
79         return false;
80     }
81 
82     handle = importedHandle;
83     return true;
84 }
85 
86 template<class M, class E>
lockYCbCrInternal(const sp<M> mapper,buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)87 YCbCrLayout HandleImporter::lockYCbCrInternal(const sp<M> mapper, buffer_handle_t& buf,
88         uint64_t cpuUsage, const IMapper::Rect& accessRegion) {
89     hidl_handle acquireFenceHandle;
90     auto buffer = const_cast<native_handle_t*>(buf);
91     YCbCrLayout layout = {};
92 
93     typename M::Rect accessRegionCopy = {accessRegion.left, accessRegion.top,
94             accessRegion.width, accessRegion.height};
95     mapper->lockYCbCr(buffer, cpuUsage, accessRegionCopy, acquireFenceHandle,
96             [&](const auto& tmpError, const auto& tmpLayout) {
97                 if (tmpError == E::NONE) {
98                     // Member by member copy from different versions of YCbCrLayout.
99                     layout.y = tmpLayout.y;
100                     layout.cb = tmpLayout.cb;
101                     layout.cr = tmpLayout.cr;
102                     layout.yStride = tmpLayout.yStride;
103                     layout.cStride = tmpLayout.cStride;
104                     layout.chromaStep = tmpLayout.chromaStep;
105                 } else {
106                     ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
107                 }
108            });
109     return layout;
110 }
111 
112 template<class M, class E>
unlockInternal(const sp<M> mapper,buffer_handle_t & buf)113 int HandleImporter::unlockInternal(const sp<M> mapper, buffer_handle_t& buf) {
114     int releaseFence = -1;
115     auto buffer = const_cast<native_handle_t*>(buf);
116 
117     mapper->unlock(
118         buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
119             if (tmpError == E::NONE) {
120                 auto fenceHandle = tmpReleaseFence.getNativeHandle();
121                 if (fenceHandle) {
122                     if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
123                         ALOGE("%s: bad release fence numInts %d numFds %d",
124                                 __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
125                         return;
126                     }
127                     releaseFence = dup(fenceHandle->data[0]);
128                     if (releaseFence < 0) {
129                         ALOGE("%s: bad release fence FD %d",
130                                 __FUNCTION__, releaseFence);
131                     }
132                 }
133             } else {
134                 ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
135             }
136         });
137     return releaseFence;
138 }
139 
140 // In IComposer, any buffer_handle_t is owned by the caller and we need to
141 // make a clone for hwcomposer2.  We also need to translate empty handle
142 // to nullptr.  This function does that, in-place.
importBuffer(buffer_handle_t & handle)143 bool HandleImporter::importBuffer(buffer_handle_t& handle) {
144     if (!handle->numFds && !handle->numInts) {
145         handle = nullptr;
146         return true;
147     }
148 
149     Mutex::Autolock lock(mLock);
150     if (!mInitialized) {
151         initializeLocked();
152     }
153 
154     if (mMapperV3 != nullptr) {
155         return importBufferInternal<IMapperV3, MapperErrorV3>(mMapperV3, handle);
156     }
157 
158     if (mMapperV2 != nullptr) {
159         return importBufferInternal<IMapper, MapperErrorV2>(mMapperV2, handle);
160     }
161 
162     ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
163     return false;
164 }
165 
freeBuffer(buffer_handle_t handle)166 void HandleImporter::freeBuffer(buffer_handle_t handle) {
167     if (!handle) {
168         return;
169     }
170 
171     Mutex::Autolock lock(mLock);
172     if (mMapperV3 == nullptr && mMapperV2 == nullptr) {
173         ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
174         return;
175     }
176 
177     if (mMapperV3 != nullptr) {
178         auto ret = mMapperV3->freeBuffer(const_cast<native_handle_t*>(handle));
179         if (!ret.isOk()) {
180             ALOGE("%s: mapper freeBuffer failed: %s",
181                     __FUNCTION__, ret.description().c_str());
182         }
183     } else {
184         auto ret = mMapperV2->freeBuffer(const_cast<native_handle_t*>(handle));
185         if (!ret.isOk()) {
186             ALOGE("%s: mapper freeBuffer failed: %s",
187                     __FUNCTION__, ret.description().c_str());
188         }
189     }
190 }
191 
importFence(const native_handle_t * handle,int & fd) const192 bool HandleImporter::importFence(const native_handle_t* handle, int& fd) const {
193     if (handle == nullptr || handle->numFds == 0) {
194         fd = -1;
195     } else if (handle->numFds == 1) {
196         fd = dup(handle->data[0]);
197         if (fd < 0) {
198             ALOGE("failed to dup fence fd %d", handle->data[0]);
199             return false;
200         }
201     } else {
202         ALOGE("invalid fence handle with %d file descriptors",
203                 handle->numFds);
204         return false;
205     }
206 
207     return true;
208 }
209 
closeFence(int fd) const210 void HandleImporter::closeFence(int fd) const {
211     if (fd >= 0) {
212         close(fd);
213     }
214 }
215 
lock(buffer_handle_t & buf,uint64_t cpuUsage,size_t size)216 void* HandleImporter::lock(
217         buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
218     Mutex::Autolock lock(mLock);
219     void *ret = 0;
220 
221     if (!mInitialized) {
222         initializeLocked();
223     }
224 
225     if (mMapperV3 == nullptr && mMapperV2 == nullptr) {
226         ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
227         return ret;
228     }
229 
230     hidl_handle acquireFenceHandle;
231     auto buffer = const_cast<native_handle_t*>(buf);
232     if (mMapperV3 != nullptr) {
233         IMapperV3::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
234         // No need to use bytesPerPixel and bytesPerStride because we are using
235         // an 1-D buffer and accressRegion.
236         mMapperV3->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
237                 [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
238                         const auto& /*bytesPerStride*/) {
239                     if (tmpError == MapperErrorV3::NONE) {
240                         ret = tmpPtr;
241                     } else {
242                         ALOGE("%s: failed to lock error %d!",
243                               __FUNCTION__, tmpError);
244                     }
245                });
246     } else {
247         IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
248         mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
249                 [&](const auto& tmpError, const auto& tmpPtr) {
250                     if (tmpError == MapperErrorV2::NONE) {
251                         ret = tmpPtr;
252                     } else {
253                         ALOGE("%s: failed to lock error %d!",
254                               __FUNCTION__, tmpError);
255                     }
256                });
257     }
258 
259     ALOGV("%s: ptr %p size: %zu", __FUNCTION__, ret, size);
260     return ret;
261 }
262 
lockYCbCr(buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)263 YCbCrLayout HandleImporter::lockYCbCr(
264         buffer_handle_t& buf, uint64_t cpuUsage,
265         const IMapper::Rect& accessRegion) {
266     Mutex::Autolock lock(mLock);
267 
268     if (!mInitialized) {
269         initializeLocked();
270     }
271 
272     if (mMapperV3 != nullptr) {
273         return lockYCbCrInternal<IMapperV3, MapperErrorV3>(
274                 mMapperV3, buf, cpuUsage, accessRegion);
275     }
276 
277     if (mMapperV2 != nullptr) {
278         return lockYCbCrInternal<IMapper, MapperErrorV2>(
279                 mMapperV2, buf, cpuUsage, accessRegion);
280     }
281 
282     ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
283     return {};
284 }
285 
unlock(buffer_handle_t & buf)286 int HandleImporter::unlock(buffer_handle_t& buf) {
287     if (mMapperV3 != nullptr) {
288         return unlockInternal<IMapperV3, MapperErrorV3>(mMapperV3, buf);
289     }
290     if (mMapperV2 != nullptr) {
291         return unlockInternal<IMapper, MapperErrorV2>(mMapperV2, buf);
292     }
293 
294     ALOGE("%s: mMapperV3 and mMapperV2 are both null!", __FUNCTION__);
295     return -1;
296 }
297 
298 } // namespace helper
299 } // namespace V1_0
300 } // namespace common
301 } // namespace camera
302 } // namespace hardware
303 } // namespace android
304