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