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 MapperError = android::hardware::graphics::mapper::V2_0::Error;
29 
HandleImporter()30 HandleImporter::HandleImporter() : mInitialized(false) {}
31 
initializeLocked()32 void HandleImporter::initializeLocked() {
33     if (mInitialized) {
34         return;
35     }
36 
37     mMapper = IMapper::getService();
38     if (mMapper == nullptr) {
39         ALOGE("%s: cannnot acccess graphics mapper HAL!", __FUNCTION__);
40         return;
41     }
42 
43     mInitialized = true;
44     return;
45 }
46 
cleanup()47 void HandleImporter::cleanup() {
48     mMapper.clear();
49     mInitialized = false;
50 }
51 
52 // In IComposer, any buffer_handle_t is owned by the caller and we need to
53 // make a clone for hwcomposer2.  We also need to translate empty handle
54 // to nullptr.  This function does that, in-place.
importBuffer(buffer_handle_t & handle)55 bool HandleImporter::importBuffer(buffer_handle_t& handle) {
56     if (!handle->numFds && !handle->numInts) {
57         handle = nullptr;
58         return true;
59     }
60 
61     Mutex::Autolock lock(mLock);
62     if (!mInitialized) {
63         initializeLocked();
64     }
65 
66     if (mMapper == nullptr) {
67         ALOGE("%s: mMapper is null!", __FUNCTION__);
68         return false;
69     }
70 
71     MapperError error;
72     buffer_handle_t importedHandle;
73     auto ret = mMapper->importBuffer(
74         hidl_handle(handle),
75         [&](const auto& tmpError, const auto& tmpBufferHandle) {
76             error = tmpError;
77             importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
78         });
79 
80     if (!ret.isOk()) {
81         ALOGE("%s: mapper importBuffer failed: %s",
82                 __FUNCTION__, ret.description().c_str());
83         return false;
84     }
85 
86     if (error != MapperError::NONE) {
87         return false;
88     }
89 
90     handle = importedHandle;
91 
92     return true;
93 }
94 
freeBuffer(buffer_handle_t handle)95 void HandleImporter::freeBuffer(buffer_handle_t handle) {
96     if (!handle) {
97         return;
98     }
99 
100     Mutex::Autolock lock(mLock);
101     if (mMapper == nullptr) {
102         ALOGE("%s: mMapper is null!", __FUNCTION__);
103         return;
104     }
105 
106     auto ret = mMapper->freeBuffer(const_cast<native_handle_t*>(handle));
107     if (!ret.isOk()) {
108         ALOGE("%s: mapper freeBuffer failed: %s",
109                 __FUNCTION__, ret.description().c_str());
110     }
111 }
112 
importFence(const native_handle_t * handle,int & fd) const113 bool HandleImporter::importFence(const native_handle_t* handle, int& fd) const {
114     if (handle == nullptr || handle->numFds == 0) {
115         fd = -1;
116     } else if (handle->numFds == 1) {
117         fd = dup(handle->data[0]);
118         if (fd < 0) {
119             ALOGE("failed to dup fence fd %d", handle->data[0]);
120             return false;
121         }
122     } else {
123         ALOGE("invalid fence handle with %d file descriptors",
124                 handle->numFds);
125         return false;
126     }
127 
128     return true;
129 }
130 
closeFence(int fd) const131 void HandleImporter::closeFence(int fd) const {
132     if (fd >= 0) {
133         close(fd);
134     }
135 }
136 
lock(buffer_handle_t & buf,uint64_t cpuUsage,size_t size)137 void* HandleImporter::lock(
138         buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
139     Mutex::Autolock lock(mLock);
140     void *ret = 0;
141     IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
142 
143     if (!mInitialized) {
144         initializeLocked();
145     }
146 
147     if (mMapper == nullptr) {
148         ALOGE("%s: mMapper is null!", __FUNCTION__);
149         return ret;
150     }
151 
152     hidl_handle acquireFenceHandle;
153     auto buffer = const_cast<native_handle_t*>(buf);
154     mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
155             [&](const auto& tmpError, const auto& tmpPtr) {
156                 if (tmpError == MapperError::NONE) {
157                     ret = tmpPtr;
158                 } else {
159                     ALOGE("%s: failed to lock error %d!",
160                           __FUNCTION__, tmpError);
161                 }
162            });
163 
164     ALOGV("%s: ptr %p size: %zu", __FUNCTION__, ret, size);
165     return ret;
166 }
167 
168 
lockYCbCr(buffer_handle_t & buf,uint64_t cpuUsage,const IMapper::Rect & accessRegion)169 YCbCrLayout HandleImporter::lockYCbCr(
170         buffer_handle_t& buf, uint64_t cpuUsage,
171         const IMapper::Rect& accessRegion) {
172     Mutex::Autolock lock(mLock);
173     YCbCrLayout layout = {};
174 
175     if (!mInitialized) {
176         initializeLocked();
177     }
178 
179     if (mMapper == nullptr) {
180         ALOGE("%s: mMapper is null!", __FUNCTION__);
181         return layout;
182     }
183 
184     hidl_handle acquireFenceHandle;
185     auto buffer = const_cast<native_handle_t*>(buf);
186     mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
187             [&](const auto& tmpError, const auto& tmpLayout) {
188                 if (tmpError == MapperError::NONE) {
189                     layout = tmpLayout;
190                 } else {
191                     ALOGE("%s: failed to lockYCbCr error %d!", __FUNCTION__, tmpError);
192                 }
193            });
194 
195     ALOGV("%s: layout y %p cb %p cr %p y_str %d c_str %d c_step %d",
196             __FUNCTION__, layout.y, layout.cb, layout.cr,
197             layout.yStride, layout.cStride, layout.chromaStep);
198     return layout;
199 }
200 
unlock(buffer_handle_t & buf)201 int HandleImporter::unlock(buffer_handle_t& buf) {
202     int releaseFence = -1;
203     auto buffer = const_cast<native_handle_t*>(buf);
204     mMapper->unlock(
205         buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
206             if (tmpError == MapperError::NONE) {
207                 auto fenceHandle = tmpReleaseFence.getNativeHandle();
208                 if (fenceHandle) {
209                     if (fenceHandle->numInts != 0 || fenceHandle->numFds != 1) {
210                         ALOGE("%s: bad release fence numInts %d numFds %d",
211                                 __FUNCTION__, fenceHandle->numInts, fenceHandle->numFds);
212                         return;
213                     }
214                     releaseFence = dup(fenceHandle->data[0]);
215                     if (releaseFence <= 0) {
216                         ALOGE("%s: bad release fence FD %d",
217                                 __FUNCTION__, releaseFence);
218                     }
219                 }
220             } else {
221                 ALOGE("%s: failed to unlock error %d!", __FUNCTION__, tmpError);
222             }
223         });
224 
225     return releaseFence;
226 }
227 
228 } // namespace helper
229 } // namespace V1_0
230 } // namespace common
231 } // namespace camera
232 } // namespace hardware
233 } // namespace android
234