1 /* 2 * Copyright (C) 2018 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 "ExtCamDevSsn (at) 3.5" 18 #include <android/log.h> 19 20 #include <utils/Trace.h> 21 #include "ExternalCameraDeviceSession.h" 22 23 namespace android { 24 namespace hardware { 25 namespace camera { 26 namespace device { 27 namespace V3_5 { 28 namespace implementation { 29 30 ExternalCameraDeviceSession::ExternalCameraDeviceSession( 31 const sp<V3_2::ICameraDeviceCallback>& callback, 32 const ExternalCameraConfig& cfg, 33 const std::vector<SupportedV4L2Format>& sortedFormats, 34 const CroppingType& croppingType, 35 const common::V1_0::helper::CameraMetadata& chars, 36 const std::string& cameraId, 37 unique_fd v4l2Fd) : 38 V3_4::implementation::ExternalCameraDeviceSession( 39 callback, cfg, sortedFormats, croppingType, chars, cameraId, std::move(v4l2Fd)) { 40 41 mCallback_3_5 = nullptr; 42 43 auto castResult = V3_5::ICameraDeviceCallback::castFrom(callback); 44 if (castResult.isOk()) { 45 sp<V3_5::ICameraDeviceCallback> callback3_5 = castResult; 46 if (callback3_5 != nullptr) { 47 mCallback_3_5 = callback3_5; 48 } 49 } 50 51 if (mCallback_3_5 != nullptr) { 52 mSupportBufMgr = true; 53 } 54 } 55 56 ExternalCameraDeviceSession::~ExternalCameraDeviceSession() { 57 closeOutputThreadImpl(); 58 } 59 60 Return<void> ExternalCameraDeviceSession::configureStreams_3_5( 61 const StreamConfiguration& requestedConfiguration, 62 ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) { 63 return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb); 64 } 65 66 Return<void> ExternalCameraDeviceSession::signalStreamFlush( 67 const hidl_vec<int32_t>& /*streamIds*/, uint32_t /*streamConfigCounter*/) { 68 return Void(); 69 } 70 71 Status ExternalCameraDeviceSession::importRequestLocked( 72 const CaptureRequest& request, 73 hidl_vec<buffer_handle_t*>& allBufPtrs, 74 hidl_vec<int>& allFences) { 75 if (mSupportBufMgr) { 76 return importRequestLockedImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ true); 77 } 78 return importRequestLockedImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ false); 79 } 80 81 82 ExternalCameraDeviceSession::BufferRequestThread::BufferRequestThread( 83 wp<ExternalCameraDeviceSession> parent, 84 sp<V3_5::ICameraDeviceCallback> callbacks) : 85 mParent(parent), 86 mCallbacks(callbacks) {} 87 88 int ExternalCameraDeviceSession::BufferRequestThread::requestBufferStart( 89 const std::vector<HalStreamBuffer>& bufReqs) { 90 if (bufReqs.empty()) { 91 ALOGE("%s: bufReqs is empty!", __FUNCTION__); 92 return -1; 93 } 94 95 { 96 std::lock_guard<std::mutex> lk(mLock); 97 if (mRequestingBuffer) { 98 ALOGE("%s: BufferRequestThread does not support more than one concurrent request!", 99 __FUNCTION__); 100 return -1; 101 } 102 103 mBufferReqs = bufReqs; 104 mRequestingBuffer = true; 105 } 106 mRequestCond.notify_one(); 107 return 0; 108 } 109 110 int ExternalCameraDeviceSession::BufferRequestThread::waitForBufferRequestDone( 111 std::vector<HalStreamBuffer>* outBufReq) { 112 std::unique_lock<std::mutex> lk(mLock); 113 if (!mRequestingBuffer) { 114 ALOGE("%s: no pending buffer request!", __FUNCTION__); 115 return -1; 116 } 117 118 if (mPendingReturnBufferReqs.empty()) { 119 std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqProcTimeoutMs); 120 auto st = mRequestDoneCond.wait_for(lk, timeout); 121 if (st == std::cv_status::timeout) { 122 ALOGE("%s: wait for buffer request finish timeout!", __FUNCTION__); 123 return -1; 124 } 125 } 126 mRequestingBuffer = false; 127 *outBufReq = std::move(mPendingReturnBufferReqs); 128 mPendingReturnBufferReqs.clear(); 129 return 0; 130 } 131 132 void ExternalCameraDeviceSession::BufferRequestThread::waitForNextRequest() { 133 ATRACE_CALL(); 134 std::unique_lock<std::mutex> lk(mLock); 135 int waitTimes = 0; 136 while (mBufferReqs.empty()) { 137 if (exitPending()) { 138 return; 139 } 140 std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqWaitTimeoutMs); 141 auto st = mRequestCond.wait_for(lk, timeout); 142 if (st == std::cv_status::timeout) { 143 waitTimes++; 144 if (waitTimes == kReqWaitTimesWarn) { 145 // BufferRequestThread just wait forever for new buffer request 146 // But it will print some periodic warning indicating it's waiting 147 ALOGV("%s: still waiting for new buffer request", __FUNCTION__); 148 waitTimes = 0; 149 } 150 } 151 } 152 153 // Fill in hidl BufferRequest 154 mHalBufferReqs.resize(mBufferReqs.size()); 155 for (size_t i = 0; i < mHalBufferReqs.size(); i++) { 156 mHalBufferReqs[i].streamId = mBufferReqs[i].streamId; 157 mHalBufferReqs[i].numBuffersRequested = 1; 158 } 159 } 160 161 bool ExternalCameraDeviceSession::BufferRequestThread::threadLoop() { 162 waitForNextRequest(); 163 if (exitPending()) { 164 return false; 165 } 166 167 ATRACE_BEGIN("HIDL requestStreamBuffers"); 168 BufferRequestStatus status; 169 hidl_vec<StreamBufferRet> bufRets; 170 auto err = mCallbacks->requestStreamBuffers(mHalBufferReqs, 171 [&status, &bufRets] 172 (BufferRequestStatus s, const hidl_vec<StreamBufferRet>& rets) { 173 status = s; 174 bufRets = std::move(rets); 175 }); 176 ATRACE_END(); 177 if (!err.isOk()) { 178 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str()); 179 return false; 180 } 181 182 std::unique_lock<std::mutex> lk(mLock); 183 if (status == BufferRequestStatus::OK || status == BufferRequestStatus::FAILED_PARTIAL) { 184 if (bufRets.size() != mHalBufferReqs.size()) { 185 ALOGE("%s: expect %zu buffer requests returned, only got %zu", 186 __FUNCTION__, mHalBufferReqs.size(), bufRets.size()); 187 return false; 188 } 189 190 auto parent = mParent.promote(); 191 if (parent == nullptr) { 192 ALOGE("%s: session has been disconnected!", __FUNCTION__); 193 return false; 194 } 195 196 hidl_vec<int> importedFences; 197 importedFences.resize(bufRets.size()); 198 for (size_t i = 0; i < bufRets.size(); i++) { 199 int streamId = bufRets[i].streamId; 200 switch (bufRets[i].val.getDiscriminator()) { 201 case StreamBuffersVal::hidl_discriminator::error: 202 continue; 203 case StreamBuffersVal::hidl_discriminator::buffers: { 204 const hidl_vec<V3_2::StreamBuffer>& hBufs = bufRets[i].val.buffers(); 205 if (hBufs.size() != 1) { 206 ALOGE("%s: expect 1 buffer returned, got %zu!", __FUNCTION__, hBufs.size()); 207 return false; 208 } 209 const V3_2::StreamBuffer& hBuf = hBufs[0]; 210 211 mBufferReqs[i].bufferId = hBuf.bufferId; 212 // TODO: create a batch import API so we don't need to lock/unlock mCbsLock 213 // repeatedly? 214 lk.unlock(); 215 Status s = parent->importBuffer(streamId, 216 hBuf.bufferId, hBuf.buffer.getNativeHandle(), 217 /*out*/&mBufferReqs[i].bufPtr, 218 /*allowEmptyBuf*/false); 219 lk.lock(); 220 221 if (s != Status::OK) { 222 ALOGE("%s: stream %d import buffer failed!", __FUNCTION__, streamId); 223 cleanupInflightFences(importedFences, i - 1); 224 return false; 225 } 226 if (!sHandleImporter.importFence(hBuf.acquireFence, 227 mBufferReqs[i].acquireFence)) { 228 ALOGE("%s: stream %d import fence failed!", __FUNCTION__, streamId); 229 cleanupInflightFences(importedFences, i - 1); 230 return false; 231 } 232 importedFences[i] = mBufferReqs[i].acquireFence; 233 } 234 break; 235 default: 236 ALOGE("%s: unkown StreamBuffersVal discrimator!", __FUNCTION__); 237 return false; 238 } 239 } 240 } else { 241 ALOGE("%s: requestStreamBuffers call failed!", __FUNCTION__); 242 } 243 244 mPendingReturnBufferReqs = std::move(mBufferReqs); 245 mBufferReqs.clear(); 246 247 lk.unlock(); 248 mRequestDoneCond.notify_one(); 249 return true; 250 } 251 252 void ExternalCameraDeviceSession::initOutputThread() { 253 if (mSupportBufMgr) { 254 mBufferRequestThread = new BufferRequestThread(this, mCallback_3_5); 255 mBufferRequestThread->run("ExtCamBufReq", PRIORITY_DISPLAY); 256 } 257 mOutputThread = new OutputThread(this, mCroppingType, mBufferRequestThread); 258 } 259 260 void ExternalCameraDeviceSession::closeOutputThreadImpl() { 261 if (mBufferRequestThread) { 262 mBufferRequestThread->requestExit(); 263 mBufferRequestThread->join(); 264 mBufferRequestThread.clear(); 265 } 266 } 267 268 void ExternalCameraDeviceSession::closeOutputThread() { 269 closeOutputThreadImpl(); 270 V3_4::implementation::ExternalCameraDeviceSession::closeOutputThread(); 271 } 272 273 ExternalCameraDeviceSession::OutputThread::OutputThread( 274 wp<ExternalCameraDeviceSession> parent, 275 CroppingType ct, 276 sp<BufferRequestThread> bufReqThread) : 277 V3_4::implementation::ExternalCameraDeviceSession::OutputThread(parent, ct), 278 mBufferRequestThread(bufReqThread) {} 279 280 ExternalCameraDeviceSession::OutputThread::~OutputThread() {} 281 282 int ExternalCameraDeviceSession::OutputThread::requestBufferStart( 283 const std::vector<HalStreamBuffer>& bufs) { 284 if (mBufferRequestThread != nullptr) { 285 return mBufferRequestThread->requestBufferStart(bufs); 286 } 287 return 0; 288 } 289 290 int ExternalCameraDeviceSession::OutputThread::waitForBufferRequestDone( 291 /*out*/std::vector<HalStreamBuffer>* outBufs) { 292 if (mBufferRequestThread != nullptr) { 293 return mBufferRequestThread->waitForBufferRequestDone(outBufs); 294 } 295 return 0; 296 } 297 298 Return<void> ExternalCameraDeviceSession::isReconfigurationRequired( 299 const V3_2::CameraMetadata& /*oldSessionParams*/, 300 const V3_2::CameraMetadata& /*newSessionParams*/, 301 ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb) { 302 //Stub implementation 303 _hidl_cb(Status::OK, true); 304 return Void(); 305 } 306 307 } // namespace implementation 308 } // namespace V3_5 309 } // namespace device 310 } // namespace camera 311 } // namespace hardware 312 } // namespace android 313