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};
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, listener, *this, *this, mBufferRecords
264 };
265
266 std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
267 for (const auto& result : results) {
268 processOneCaptureResultLocked(states, result.v3_2, result.physicalCameraMetadata);
269 }
270 return hardware::Void();
271 }
272
processCaptureResult(const hardware::hidl_vec<hardware::camera::device::V3_2::CaptureResult> & results)273 hardware::Return<void> Camera3OfflineSession::processCaptureResult(
274 const hardware::hidl_vec<
275 hardware::camera::device::V3_2::CaptureResult>& results) {
276 // TODO: changed impl to call into processCaptureResult_3_4 instead?
277 // might need to figure how to reduce copy though.
278 sp<NotificationListener> listener;
279 {
280 std::lock_guard<std::mutex> lock(mLock);
281 if (mStatus != STATUS_ACTIVE) {
282 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
283 return hardware::Void();
284 }
285 listener = mListener.promote();
286 }
287
288 hardware::hidl_vec<hardware::camera::device::V3_4::PhysicalCameraMetadata> noPhysMetadata;
289
290 CaptureOutputStates states {
291 mId,
292 mOfflineReqsLock, mLastCompletedRegularFrameNumber,
293 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
294 mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
295 mNextShutterFrameNumber,
296 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
297 mNextResultFrameNumber,
298 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
299 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
300 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
301 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
302 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
303 };
304
305 std::lock_guard<std::mutex> lock(mProcessCaptureResultLock);
306 for (const auto& result : results) {
307 processOneCaptureResultLocked(states, result, noPhysMetadata);
308 }
309 return hardware::Void();
310 }
311
notify(const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg> & msgs)312 hardware::Return<void> Camera3OfflineSession::notify(
313 const hardware::hidl_vec<hardware::camera::device::V3_2::NotifyMsg>& msgs) {
314 sp<NotificationListener> listener;
315 {
316 std::lock_guard<std::mutex> lock(mLock);
317 if (mStatus != STATUS_ACTIVE) {
318 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
319 return hardware::Void();
320 }
321 listener = mListener.promote();
322 }
323
324 CaptureOutputStates states {
325 mId,
326 mOfflineReqsLock, mLastCompletedRegularFrameNumber,
327 mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
328 mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
329 mNextShutterFrameNumber,
330 mNextReprocessShutterFrameNumber, mNextZslStillShutterFrameNumber,
331 mNextResultFrameNumber,
332 mNextReprocessResultFrameNumber, mNextZslStillResultFrameNumber,
333 mUseHalBufManager, mUsePartialResult, mNeedFixupMonochromeTags,
334 mNumPartialResults, mVendorTagId, mDeviceInfo, mPhysicalDeviceInfoMap,
335 mResultMetadataQueue, mDistortionMappers, mZoomRatioMappers, mRotateAndCropMappers,
336 mTagMonitor, mInputStream, mOutputStreams, listener, *this, *this, mBufferRecords
337 };
338 for (const auto& msg : msgs) {
339 camera3::notify(states, msg);
340 }
341 return hardware::Void();
342 }
343
requestStreamBuffers(const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest> & bufReqs,requestStreamBuffers_cb _hidl_cb)344 hardware::Return<void> Camera3OfflineSession::requestStreamBuffers(
345 const hardware::hidl_vec<hardware::camera::device::V3_5::BufferRequest>& bufReqs,
346 requestStreamBuffers_cb _hidl_cb) {
347 {
348 std::lock_guard<std::mutex> lock(mLock);
349 if (mStatus != STATUS_ACTIVE) {
350 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
351 return hardware::Void();
352 }
353 }
354
355 RequestBufferStates states {
356 mId, mRequestBufferInterfaceLock, mUseHalBufManager, mOutputStreams,
357 *this, mBufferRecords, *this};
358 camera3::requestStreamBuffers(states, bufReqs, _hidl_cb);
359 return hardware::Void();
360 }
361
returnStreamBuffers(const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer> & buffers)362 hardware::Return<void> Camera3OfflineSession::returnStreamBuffers(
363 const hardware::hidl_vec<hardware::camera::device::V3_2::StreamBuffer>& buffers) {
364 {
365 std::lock_guard<std::mutex> lock(mLock);
366 if (mStatus != STATUS_ACTIVE) {
367 ALOGE("%s called in wrong state %d", __FUNCTION__, mStatus);
368 return hardware::Void();
369 }
370 }
371
372 ReturnBufferStates states {
373 mId, mUseHalBufManager, mOutputStreams, mBufferRecords};
374 camera3::returnStreamBuffers(states, buffers);
375 return hardware::Void();
376 }
377
setErrorState(const char * fmt,...)378 void Camera3OfflineSession::setErrorState(const char *fmt, ...) {
379 ATRACE_CALL();
380 std::lock_guard<std::mutex> lock(mLock);
381 va_list args;
382 va_start(args, fmt);
383
384 setErrorStateLockedV(fmt, args);
385
386 va_end(args);
387
388 //FIXME: automatically disconnect here?
389 }
390
setErrorStateLocked(const char * fmt,...)391 void Camera3OfflineSession::setErrorStateLocked(const char *fmt, ...) {
392 va_list args;
393 va_start(args, fmt);
394
395 setErrorStateLockedV(fmt, args);
396
397 va_end(args);
398 }
399
setErrorStateLockedV(const char * fmt,va_list args)400 void Camera3OfflineSession::setErrorStateLockedV(const char *fmt, va_list args) {
401 // Print out all error messages to log
402 String8 errorCause = String8::formatV(fmt, args);
403 ALOGE("Camera %s: %s", mId.string(), errorCause.string());
404
405 // But only do error state transition steps for the first error
406 if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
407
408 mErrorCause = errorCause;
409
410 mStatus = STATUS_ERROR;
411
412 // Notify upstream about a device error
413 sp<NotificationListener> listener = mListener.promote();
414 if (listener != NULL) {
415 listener->notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
416 CaptureResultExtras());
417 }
418
419 // Save stack trace. View by dumping it later.
420 CameraTraces::saveTrace();
421 }
422
onInflightEntryRemovedLocked(nsecs_t)423 void Camera3OfflineSession::onInflightEntryRemovedLocked(nsecs_t /*duration*/) {
424 if (mOfflineReqs.size() == 0) {
425 std::lock_guard<std::mutex> lock(mRequestBufferInterfaceLock);
426 mAllowRequestBuffer = false;
427 }
428 }
429
checkInflightMapLengthLocked()430 void Camera3OfflineSession::checkInflightMapLengthLocked() {
431 // Intentional empty impl.
432 }
433
onInflightMapFlushedLocked()434 void Camera3OfflineSession::onInflightMapFlushedLocked() {
435 // Intentional empty impl.
436 }
437
startRequestBuffer()438 bool Camera3OfflineSession::startRequestBuffer() {
439 return mAllowRequestBuffer;
440 }
441
endRequestBuffer()442 void Camera3OfflineSession::endRequestBuffer() {
443 // Intentional empty impl.
444 }
445
getWaitDuration()446 nsecs_t Camera3OfflineSession::getWaitDuration() {
447 const nsecs_t kBaseGetBufferWait = 3000000000; // 3 sec.
448 return kBaseGetBufferWait;
449 }
450
getInflightBufferKeys(std::vector<std::pair<int32_t,int32_t>> * out)451 void Camera3OfflineSession::getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out) {
452 mBufferRecords.getInflightBufferKeys(out);
453 }
454
getInflightRequestBufferKeys(std::vector<uint64_t> * out)455 void Camera3OfflineSession::getInflightRequestBufferKeys(std::vector<uint64_t>* out) {
456 mBufferRecords.getInflightRequestBufferKeys(out);
457 }
458
getAllStreams()459 std::vector<sp<Camera3StreamInterface>> Camera3OfflineSession::getAllStreams() {
460 std::vector<sp<Camera3StreamInterface>> ret;
461 bool hasInputStream = mInputStream != nullptr;
462 ret.reserve(mOutputStreams.size() + ((hasInputStream) ? 1 : 0));
463 if (hasInputStream) {
464 ret.push_back(mInputStream);
465 }
466 for (size_t i = 0; i < mOutputStreams.size(); i++) {
467 ret.push_back(mOutputStreams[i]);
468 }
469 return ret;
470 }
471
info() const472 const CameraMetadata& Camera3OfflineSession::info() const {
473 return mDeviceInfo;
474 }
475
476 }; // namespace android
477