• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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