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 32 HandleImporter::HandleImporter() : mInitialized(false) {} 33 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 55 void HandleImporter::cleanup() { 56 mMapperV3.clear(); 57 mMapperV2.clear(); 58 mInitialized = false; 59 } 60 61 template<class M, class E> 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> 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> 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. 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 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 192 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 210 void HandleImporter::closeFence(int fd) const { 211 if (fd >= 0) { 212 close(fd); 213 } 214 } 215 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 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 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