1 /*
2 * Copyright (C) 2019 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 "Camera3-OffLnSsn"
18 #define ATRACE_TAG ATRACE_TAG_CAMERA
19 //#define LOG_NDEBUG 0
20 //#define LOG_NNDEBUG 0 // Per-frame verbose logging
21
22 #ifdef LOG_NNDEBUG
23 #define ALOGVV(...) ALOGV(__VA_ARGS__)
24 #else
25 #define ALOGVV(...) ((void)0)
26 #endif
27
28 #include <inttypes.h>
29
30 #include <utils/Trace.h>
31
32 #include <android/hardware/camera2/ICameraDeviceCallbacks.h>
33
34 #include "device3/Camera3OfflineSession.h"
35 #include "device3/Camera3OutputStream.h"
36 #include "device3/Camera3InputStream.h"
37 #include "device3/Camera3SharedOutputStream.h"
38 #include "utils/CameraTraces.h"
39
40 using namespace android::camera3;
41 using namespace android::hardware::camera;
42
43 namespace android {
44
Camera3OfflineSession(const String8 & id,const sp<camera3::Camera3Stream> & inputStream,const camera3::StreamSet & offlineStreamSet,camera3::BufferRecords && bufferRecords,const camera3::InFlightRequestMap & offlineReqs,const Camera3OfflineStates & offlineStates,sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession)45 Camera3OfflineSession::Camera3OfflineSession(const String8 &id,
46 const sp<camera3::Camera3Stream>& inputStream,
47 const camera3::StreamSet& offlineStreamSet,
48 camera3::BufferRecords&& bufferRecords,
49 const camera3::InFlightRequestMap& offlineReqs,
50 const Camera3OfflineStates& offlineStates,
51 sp<hardware::camera::device::V3_6::ICameraOfflineSession> offlineSession) :
52 mId(id),
53 mInputStream(inputStream),
54 mOutputStreams(offlineStreamSet),
55 mBufferRecords(std::move(bufferRecords)),
56 mOfflineReqs(offlineReqs),
57 mSession(offlineSession),
58 mTagMonitor(offlineStates.mTagMonitor),
59 mVendorTagId(offlineStates.mVendorTagId),
60 mUseHalBufManager(offlineStates.mUseHalBufManager),
61 mNeedFixupMonochromeTags(offlineStates.mNeedFixupMonochromeTags),
62 mUsePartialResult(offlineStates.mUsePartialResult),
63 mNumPartialResults(offlineStates.mNumPartialResults),
64 mLastCompletedRegularFrameNumber(offlineStates.mLastCompletedRegularFrameNumber),
65 mLastCompletedReprocessFrameNumber(offlineStates.mLastCompletedReprocessFrameNumber),
66 mLastCompletedZslFrameNumber(offlineStates.mLastCompletedZslFrameNumber),
67 mNextResultFrameNumber(offlineStates.mNextResultFrameNumber),
68 mNextReprocessResultFrameNumber(offlineStates.mNextReprocessResultFrameNumber),
69 mNextZslStillResultFrameNumber(offlineStates.mNextZslStillResultFrameNumber),
70 mNextShutterFrameNumber(offlineStates.mNextShutterFrameNumber),
71 mNextReprocessShutterFrameNumber(offlineStates.mNextReprocessShutterFrameNumber),
72 mNextZslStillShutterFrameNumber(offlineStates.mNextZslStillShutterFrameNumber),
73 mDeviceInfo(offlineStates.mDeviceInfo),
74 mPhysicalDeviceInfoMap(offlineStates.mPhysicalDeviceInfoMap),
75 mDistortionMappers(offlineStates.mDistortionMappers),
76 mZoomRatioMappers(offlineStates.mZoomRatioMappers),
77 mRotateAndCropMappers(offlineStates.mRotateAndCropMappers),
78 mStatus(STATUS_UNINITIALIZED) {
79 ATRACE_CALL();
80 ALOGV("%s: Created offline session for camera %s", __FUNCTION__, mId.string());
81 }
82
~Camera3OfflineSession()83 Camera3OfflineSession::~Camera3OfflineSession() {
84 ATRACE_CALL();
85 ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.string());
86 disconnectImpl();
87 }
88
getId() const89 const String8& Camera3OfflineSession::getId() const {
90 return mId;
91 }
92
initialize(wp<NotificationListener> listener)93 status_t Camera3OfflineSession::initialize(wp<NotificationListener> listener) {
94 ATRACE_CALL();
95
96 if (mSession == nullptr) {
97 ALOGE("%s: HIDL session is null!", __FUNCTION__);
98 return DEAD_OBJECT;
99 }
100
101 {
102 std::lock_guard<std::mutex> lock(mLock);
103
104 mListener = listener;
105
106 // setup result FMQ
107 std::unique_ptr<ResultMetadataQueue>& resQueue = mResultMetadataQueue;
108 auto resultQueueRet = mSession->getCaptureResultMetadataQueue(
109 [&resQueue](const auto& descriptor) {
110 resQueue = std::make_unique<ResultMetadataQueue>(descriptor);
111 if (!resQueue->isValid() || resQueue->availableToWrite() <= 0) {
112 ALOGE("HAL returns empty result metadata fmq, not use it");
113 resQueue = nullptr;
114 // Don't use resQueue onwards.
115 }
116 });
117 if (!resultQueueRet.isOk()) {
118 ALOGE("Transaction error when getting result metadata queue from camera session: %s",
119 resultQueueRet.description().c_str());
120 return DEAD_OBJECT;
121 }
122 mStatus = STATUS_ACTIVE;
123 }
124
125 mSession->setCallback(this);
126
127 return OK;
128 }
129
dump(int)130 status_t Camera3OfflineSession::dump(int /*fd*/) {
131 ATRACE_CALL();
132 std::lock_guard<std::mutex> il(mInterfaceLock);
133 return OK;
134 }
135
disconnect()136 status_t Camera3OfflineSession::disconnect() {
137 ATRACE_CALL();
138 return disconnectImpl();
139 }
140
disconnectImpl()141 status_t Camera3OfflineSession::disconnectImpl() {
142 ATRACE_CALL();
143 std::lock_guard<std::mutex> il(mInterfaceLock);
144
145 sp<NotificationListener> listener;
146 {
147 std::lock_guard<std::mutex> lock(mLock);
148 if (mStatus == STATUS_CLOSED) {
149 return OK; // don't close twice
150 } else if (mStatus == STATUS_ERROR) {
151 ALOGE("%s: offline session %s shutting down in error state",
152 __FUNCTION__, mId.string());
153 }
154 listener = mListener.promote();
155 }
156
157 ALOGV("%s: E", __FUNCTION__);
158
159 {
160 std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
161 mAllowRequestBuffer = false;
162 }
163
164 std::vector<wp<Camera3StreamInterface>> streams;
165 streams.reserve(mOutputStreams.size() + (mInputStream != nullptr ? 1 : 0));
166 for (size_t i = 0; i < mOutputStreams.size(); i++) {
167 streams.push_back(mOutputStreams[i]);
168 }
169 if (mInputStream != nullptr) {
170 streams.push_back(mInputStream);
171 }
172
173 if (mSession != nullptr) {
174 mSession->close();
175 }
176
177 FlushInflightReqStates states {
178 mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
179 listener, *this, mBufferRecords, *this, mSessionStatsBuilder};
180
181 camera3::flushInflightRequests(states);
182
183 {
184 std::lock_guard<std::mutex> lock(mLock);
185 mSession.clear();
186 mOutputStreams.clear();
187 mInputStream.clear();
188 mStatus = STATUS_CLOSED;
189 }
190
191 for (auto& weakStream : streams) {
192 sp<Camera3StreamInterface> stream = weakStream.promote();
193 if (stream != nullptr) {
194 ALOGE("%s: Stream %d leaked! strong reference (%d)!",
195 __FUNCTION__, stream->getId(), stream->getStrongCount() - 1);
196 }
197 }
198
199 ALOGV("%s: X", __FUNCTION__);
200 return OK;
201 }
202
waitForNextFrame(nsecs_t timeout)203 status_t Camera3OfflineSession::waitForNextFrame(nsecs_t timeout) {
204 ATRACE_CALL();
205 std::unique_lock<std::mutex> lk(mOutputLock);
206
207 while (mResultQueue.empty()) {
208 auto st = mResultSignal.wait_for(lk, std::chrono::nanoseconds(timeout));
209 if (st == std::cv_status::timeout) {
210 return TIMED_OUT;
211 }
212 }
213 return OK;
214 }
215
getNextResult(CaptureResult * frame)216 status_t Camera3OfflineSession::getNextResult(CaptureResult* frame) {
217 ATRACE_CALL();
218 std::lock_guard<std::mutex> l(mOutputLock);
219
220 if (mResultQueue.empty()) {
221 return NOT_ENOUGH_DATA;
222 }
223
224 if (frame == nullptr) {
225 ALOGE("%s: argument cannot be NULL", __FUNCTION__);
226 return BAD_VALUE;
227 }
228
229 CaptureResult &result = *(mResultQueue.begin());
230 frame->mResultExtras = result.mResultExtras;
231 frame->mMetadata.acquire(result.mMetadata);
232 frame->mPhysicalMetadatas = std::move(result.mPhysicalMetadatas);
233 mResultQueue.erase(mResultQueue.begin());
234
235 return OK;
236 }
237
processCaptureResult_3_4(const hardware::hidl_vec<hardware::camera::device::V3_4::CaptureResult> & results)238 hardware::Return<void> Camera3OfflineSession::processCaptureResult_3_4(
239 const hardware::hidl_vec<
240 hardware::camera::device::V3_4::CaptureResult>& results) {
241 sp<NotificationListener> listener;
242 {
243 std::lock_guard<std::mutex> lock(mLock);
244 if (mStatus != STATUS_ACTIVE) {
245 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
246 return hardware::Void();
247 }
248 listener = mListener.promote();
249 }
250
251 CaptureOutputStates states {
252 mId,
253 mOfflineReqsLock, mLastCompletedRegularFrameNumber,
254 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
255 mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
256 mNextShutterFrameNumber,
257 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
258 mNextResultFrameNumber,
259 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
260 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
261 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
262 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
263 mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
264 mBufferRecords, /*legacyClient*/ false
265 };
266
267 std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
268 for (const auto& result : results) {
269 processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
270 }
271 return hardware::Void();
272 }
273
processCaptureResult(const hardware::hidl_vec<hardware::camera::device::V3_2::CaptureResult> & results)274 hardware::Return<void> Camera3OfflineSession::processCaptureResult(
275 const hardware::hidl_vec<
276 hardware::camera::device::V3_2::CaptureResult>& results) {
277 // TODO: changed impl to call into processCaptureResult_3_4 instead?
278 // might need to figure how to reduce copy though.
279 sp<NotificationListener> listener;
280 {
281 std::lock_guard<std::mutex> lock(mLock);
282 if (mStatus != STATUS_ACTIVE) {
283 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
284 return hardware::Void();
285 }
286 listener = mListener.promote();
287 }
288
289 hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
290
291 CaptureOutputStates states {
292 mId,
293 mOfflineReqsLock, mLastCompletedRegularFrameNumber,
294 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
295 mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
296 mNextShutterFrameNumber,
297 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
298 mNextResultFrameNumber,
299 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
300 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
301 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
302 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
303 mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
304 mBufferRecords, /*legacyClient*/ false
305 };
306
307 std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
308 for (const auto& result : results) {
309 processOneCaptureResultLocked(states, result, noPhysMetadata);
310 }
311 return hardware::Void();
312 }
313
notify(const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg> & msgs)314 hardware::Return<void> Camera3OfflineSession::notify(
315 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
316 sp<NotificationListener> listener;
317 {
318 std::lock_guard<std::mutex> lock(mLock);
319 if (mStatus != STATUS_ACTIVE) {
320 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
321 return hardware::Void();
322 }
323 listener = mListener.promote();
324 }
325
326 CaptureOutputStates states {
327 mId,
328 mOfflineReqsLock, mLastCompletedRegularFrameNumber,
329 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
330 mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
331 mNextShutterFrameNumber,
332 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
333 mNextResultFrameNumber,
334 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
335 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
336 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
337 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
338 mTagMonitor, mInputStream, mOutputStreams, mSessionStatsBuilder, listener, *this, *this,
339 mBufferRecords, /*legacyClient*/ false
340 };
341 for (const auto& msg : msgs) {
342 camera3::notify(states, msg);
343 }
344 return hardware::Void();
345 }
346
requestStreamBuffers(const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest> & bufReqs,requestStreamBuffers_cb _hidl_cb)347 hardware::Return<void> Camera3OfflineSession::requestStreamBuffers(
348 const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
349 requestStreamBuffers_cb _hidl_cb) {
350 {
351 std::lock_guard<std::mutex> lock(mLock);
352 if (mStatus != STATUS_ACTIVE) {
353 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
354 return hardware::Void();
355 }
356 }
357
358 RequestBufferStates states {
359 mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder,
360 *this, mBufferRecords, *this};
361 camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
362 return hardware::Void();
363 }
364
returnStreamBuffers(const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer> & buffers)365 hardware::Return<void> Camera3OfflineSession::returnStreamBuffers(
366 const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
367 {
368 std::lock_guard<std::mutex> lock(mLock);
369 if (mStatus != STATUS_ACTIVE) {
370 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
371 return hardware::Void();
372 }
373 }
374
375 ReturnBufferStates states {
376 mId, mUseHalBufManager, mOutputStreams, mSessionStatsBuilder, mBufferRecords};
377 camera3::returnStreamBuffers(states, buffers);
378 return hardware::Void();
379 }
380
setErrorState(const char * fmt,...)381 void Camera3OfflineSession::setErrorState(const char *fmt, ...) {
382 ATRACE_CALL();
383 std::lock_guard<std::mutex> lock(mLock);
384 va_list args;
385 va_start(args, fmt);
386
387 setErrorStateLockedV(fmt, args);
388
389 va_end(args);
390
391 //FIXME: automatically disconnect here?
392 }
393
setErrorStateLocked(const char * fmt,...)394 void Camera3OfflineSession::setErrorStateLocked(const char *fmt, ...) {
395 va_list args;
396 va_start(args, fmt);
397
398 setErrorStateLockedV(fmt, args);
399
400 va_end(args);
401 }
402
setErrorStateLockedV(const char * fmt,va_list args)403 void Camera3OfflineSession::setErrorStateLockedV(const char *fmt, va_list args) {
404 // Print out all error messages to log
405 String8 errorCause = String8::formatV(fmt, args);
406 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
407
408 // But only do error state transition steps for the first error
409 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
410
411 mErrorCause = errorCause;
412
413 mStatus = STATUS_ERROR;
414
415 // Notify upstream about a device error
416 sp<NotificationListener> listener = mListener.promote();
417 if (listener != NULL) {
418 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
419 CaptureResultExtras());
420 }
421
422 // Save stack trace. View by dumping it later.
423 CameraTraces::saveTrace();
424 }
425
onInflightEntryRemovedLocked(nsecs_t)426 void Camera3OfflineSession::onInflightEntryRemovedLocked(nsecs_t /*duration*/) {
427 if (mOfflineReqs.size() == 0) {
428 std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
429 mAllowRequestBuffer = false;
430 }
431 }
432
checkInflightMapLengthLocked()433 void Camera3OfflineSession::checkInflightMapLengthLocked() {
434 // Intentional empty impl.
435 }
436
onInflightMapFlushedLocked()437 void Camera3OfflineSession::onInflightMapFlushedLocked() {
438 // Intentional empty impl.
439 }
440
startRequestBuffer()441 bool Camera3OfflineSession::startRequestBuffer() {
442 return mAllowRequestBuffer;
443 }
444
endRequestBuffer()445 void Camera3OfflineSession::endRequestBuffer() {
446 // Intentional empty impl.
447 }
448
getWaitDuration()449 nsecs_t Camera3OfflineSession::getWaitDuration() {
450 const nsecs_t kBaseGetBufferWait = 3000000000; // 3 sec.
451 return kBaseGetBufferWait;
452 }
453
getInflightBufferKeys(std::vector<std::pair<int32_t,int32_t>> * out)454 void Camera3OfflineSession::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
455 mBufferRecords.getInflightBufferKeys(out);
456 }
457
getInflightRequestBufferKeys(std::vector<uint64_t> * out)458 void Camera3OfflineSession::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
459 mBufferRecords.getInflightRequestBufferKeys(out);
460 }
461
getAllStreams()462 std::vector<sp<Camera3StreamInterface>> Camera3OfflineSession::getAllStreams() {
463 std::vector<sp<Camera3StreamInterface>> ret;
464 bool hasInputStream = mInputStream != nullptr;
465 ret.reserve(mOutputStreams.size() + ((hasInputStream) ? 1 : 0));
466 if (hasInputStream) {
467 ret.push_back(mInputStream);
468 }
469 for (size_t i = 0; i < mOutputStreams.size(); i++) {
470 ret.push_back(mOutputStreams[i]);
471 }
472 return ret;
473 }
474
info() const475 const CameraMetadata& Camera3OfflineSession::info() const {
476 return mDeviceInfo;
477 }
478
479 }; // namespace android
480