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