blob: 5b3024b238ea47b89a157a8ceaf9161ccfbc52d0 [file] [log] [blame]
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001/*
2 * Copyright (C) 2016 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 "CamDevSession@3.2-impl"
18#include <android/log.h>
19
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080020#include <set>
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070021#include <utils/Trace.h>
22#include <hardware/gralloc.h>
23#include <hardware/gralloc1.h>
24#include "CameraDeviceSession.h"
25
26namespace android {
27namespace hardware {
28namespace camera {
29namespace device {
30namespace V3_2 {
31namespace implementation {
32
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080033HandleImporter& CameraDeviceSession::sHandleImporter = HandleImporter::getInstance();
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080034const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070035
36CameraDeviceSession::CameraDeviceSession(
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080037 camera3_device_t* device,
38 const camera_metadata_t* deviceInfo,
39 const sp<ICameraDeviceCallback>& callback) :
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070040 camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
41 mDevice(device),
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080042 mResultBatcher(callback) {
43
44 mDeviceInfo = deviceInfo;
45 uint32_t numPartialResults = 1;
46 camera_metadata_entry partialResultsCount =
47 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
48 if (partialResultsCount.count > 0) {
49 numPartialResults = partialResultsCount.data.i32[0];
50 }
51 mResultBatcher.setNumPartialResults(numPartialResults);
52
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070053 mInitFail = initialize();
54}
55
56bool CameraDeviceSession::initialize() {
57 /** Initialize device with callback functions */
58 ATRACE_BEGIN("camera3->initialize");
59 status_t res = mDevice->ops->initialize(mDevice, this);
60 ATRACE_END();
61
62 if (res != OK) {
63 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
64 __FUNCTION__, strerror(-res), res);
65 mDevice->common.close(&mDevice->common);
66 mClosed = true;
67 return true;
68 }
69 return false;
70}
71
72CameraDeviceSession::~CameraDeviceSession() {
73 if (!isClosed()) {
74 ALOGE("CameraDeviceSession deleted before close!");
75 close();
76 }
77}
78
79bool CameraDeviceSession::isClosed() {
80 Mutex::Autolock _l(mStateLock);
81 return mClosed;
82}
83
84Status CameraDeviceSession::initStatus() const {
85 Mutex::Autolock _l(mStateLock);
86 Status status = Status::OK;
87 if (mInitFail) {
88 status = Status::INTERNAL_ERROR;
89 } else if (mDisconnected) {
90 status = Status::CAMERA_DISCONNECTED;
91 } else if (mClosed) {
92 status = Status::INTERNAL_ERROR;
93 }
94 return status;
95}
96
97void CameraDeviceSession::disconnect() {
98 Mutex::Autolock _l(mStateLock);
99 mDisconnected = true;
100 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
101 if (!mClosed) {
102 mDevice->common.close(&mDevice->common);
103 mClosed = true;
104 }
105}
106
107void CameraDeviceSession::dumpState(const native_handle_t* fd) {
108 if (!isClosed()) {
109 mDevice->ops->dump(mDevice, fd->data[0]);
110 }
111}
112
113Status CameraDeviceSession::importRequest(
114 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800115 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700116 hidl_vec<int>& allFences) {
117 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800118 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700119 size_t numOutputBufs = request.outputBuffers.size();
120 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
121 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800122 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800123 hidl_vec<uint64_t> allBufIds;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700124 allBufs.resize(numBufs);
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800125 allBufIds.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800126 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700127 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800128 std::vector<int32_t> streamIds(numBufs);
129
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700130 for (size_t i = 0; i < numOutputBufs; i++) {
131 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800132 allBufIds[i] = request.outputBuffers[i].bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800133 allBufPtrs[i] = &allBufs[i];
134 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700135 }
136 if (hasInputBuf) {
137 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800138 allBufIds[numOutputBufs] = request.inputBuffer.bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800139 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
140 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700141 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800142
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700143 for (size_t i = 0; i < numBufs; i++) {
144 buffer_handle_t buf = allBufs[i];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800145 uint64_t bufId = allBufIds[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800146 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800147 if (cbs.count(bufId) == 0) {
148 if (buf == nullptr) {
149 ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
150 return Status::ILLEGAL_ARGUMENT;
151 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800152 // Register a newly seen buffer
153 buffer_handle_t importedBuf = buf;
154 sHandleImporter.importBuffer(importedBuf);
155 if (importedBuf == nullptr) {
156 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
157 return Status::INTERNAL_ERROR;
158 } else {
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800159 cbs[bufId] = importedBuf;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800160 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700161 }
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800162 allBufPtrs[i] = &cbs[bufId];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700163 }
164
165 // All buffers are imported. Now validate output buffer acquire fences
166 for (size_t i = 0; i < numOutputBufs; i++) {
167 if (!sHandleImporter.importFence(
168 request.outputBuffers[i].acquireFence, allFences[i])) {
169 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800170 cleanupInflightFences(allFences, i);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700171 return Status::INTERNAL_ERROR;
172 }
173 }
174
175 // Validate input buffer acquire fences
176 if (hasInputBuf) {
177 if (!sHandleImporter.importFence(
178 request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
179 ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800180 cleanupInflightFences(allFences, numOutputBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700181 return Status::INTERNAL_ERROR;
182 }
183 }
184 return Status::OK;
185}
186
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800187void CameraDeviceSession::cleanupInflightFences(
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700188 hidl_vec<int>& allFences, size_t numFences) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700189 for (size_t j = 0; j < numFences; j++) {
190 sHandleImporter.closeFence(allFences[j]);
191 }
192}
193
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800194CameraDeviceSession::ResultBatcher::ResultBatcher(
195 const sp<ICameraDeviceCallback>& callback) : mCallback(callback) {};
196
197bool CameraDeviceSession::ResultBatcher::InflightBatch::allDelivered() const {
198 if (!mShutterDelivered) return false;
199
200 if (mPartialResultProgress < mNumPartialResults) {
201 return false;
202 }
203
204 for (const auto& pair : mBatchBufs) {
205 if (!pair.second.mDelivered) {
206 return false;
207 }
208 }
209 return true;
210}
211
212void CameraDeviceSession::ResultBatcher::setNumPartialResults(uint32_t n) {
213 Mutex::Autolock _l(mLock);
214 mNumPartialResults = n;
215}
216
217void CameraDeviceSession::ResultBatcher::setBatchedStreams(
218 const std::vector<int>& streamsToBatch) {
219 Mutex::Autolock _l(mLock);
220 mStreamsToBatch = streamsToBatch;
221}
222
223void CameraDeviceSession::ResultBatcher::registerBatch(
224 const hidl_vec<CaptureRequest>& requests) {
225 auto batch = std::make_shared<InflightBatch>();
226 batch->mFirstFrame = requests[0].frameNumber;
227 batch->mBatchSize = requests.size();
228 batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
229 batch->mNumPartialResults = mNumPartialResults;
230 for (int id : mStreamsToBatch) {
231 batch->mBatchBufs[id] = InflightBatch::BufferBatch();
232 }
233 Mutex::Autolock _l(mLock);
234 mInflightBatches.push_back(batch);
235}
236
237std::pair<int, std::shared_ptr<CameraDeviceSession::ResultBatcher::InflightBatch>>
238CameraDeviceSession::ResultBatcher::getBatch(
239 uint32_t frameNumber) {
240 Mutex::Autolock _l(mLock);
241 int numBatches = mInflightBatches.size();
242 if (numBatches == 0) {
243 return std::make_pair(NOT_BATCHED, nullptr);
244 }
245 uint32_t frameMin = mInflightBatches[0]->mFirstFrame;
246 uint32_t frameMax = mInflightBatches[numBatches - 1]->mLastFrame;
247 if (frameNumber < frameMin || frameNumber > frameMax) {
248 return std::make_pair(NOT_BATCHED, nullptr);
249 }
250 for (int i = 0; i < numBatches; i++) {
251 if (frameNumber >= mInflightBatches[i]->mFirstFrame &&
252 frameNumber <= mInflightBatches[i]->mLastFrame) {
253 return std::make_pair(i, mInflightBatches[i]);
254 }
255 }
256 return std::make_pair(NOT_BATCHED, nullptr);
257}
258
259void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
260 Mutex::Autolock _l(mLock);
261 if (mInflightBatches.size() > 0) {
262 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
263 bool shouldRemove = false;
264 {
265 Mutex::Autolock _l(batch->mLock);
266 if (batch->allDelivered()) {
267 batch->mRemoved = true;
268 shouldRemove = true;
269 }
270 }
271 if (shouldRemove) {
272 mInflightBatches.pop_front();
273 }
274 }
275}
276
277void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch) {
278 if (batch->mShutterDelivered) {
279 ALOGW("%s: batch shutter callback already sent!", __FUNCTION__);
280 return;
281 }
282
283 mCallback->notify(batch->mShutterMsgs);
284 batch->mShutterDelivered = true;
285 batch->mShutterMsgs.clear();
286}
287
288void CameraDeviceSession::ResultBatcher::freeReleaseFences(hidl_vec<CaptureResult>& results) {
289 for (auto& result : results) {
290 if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
291 native_handle_t* handle = const_cast<native_handle_t*>(
292 result.inputBuffer.releaseFence.getNativeHandle());
293 native_handle_delete(handle);
294 }
295 for (auto& buf : result.outputBuffers) {
296 if (buf.releaseFence.getNativeHandle() != nullptr) {
297 native_handle_t* handle = const_cast<native_handle_t*>(
298 buf.releaseFence.getNativeHandle());
299 native_handle_delete(handle);
300 }
301 }
302 }
303 return;
304}
305
306void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
307 sendBatchBuffersLocked(batch, mStreamsToBatch);
308}
309
310void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
311 std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
312 size_t batchSize = 0;
313 for (int streamId : streams) {
314 auto it = batch->mBatchBufs.find(streamId);
315 if (it != batch->mBatchBufs.end()) {
316 InflightBatch::BufferBatch& bb = it->second;
317 if (bb.mDelivered) {
318 continue;
319 }
320 if (bb.mBuffers.size() > batchSize) {
321 batchSize = bb.mBuffers.size();
322 }
323 } else {
324 ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
325 return;
326 }
327 }
328
329 if (batchSize == 0) {
330 ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
331 for (int streamId : streams) {
332 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
333 bb.mDelivered = true;
334 }
335 return;
336 }
337
338 hidl_vec<CaptureResult> results;
339 results.resize(batchSize);
340 for (size_t i = 0; i < batchSize; i++) {
341 results[i].frameNumber = batch->mFirstFrame + i;
342 results[i].partialResult = 0; // 0 for buffer only results
343 results[i].inputBuffer.streamId = -1;
344 results[i].inputBuffer.bufferId = 0;
345 results[i].inputBuffer.buffer = nullptr;
346 std::vector<StreamBuffer> outBufs;
347 for (int streamId : streams) {
348 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
349 if (bb.mDelivered) {
350 continue;
351 }
352 if (i < bb.mBuffers.size()) {
353 outBufs.push_back(bb.mBuffers[i]);
354 }
355 }
356 results[i].outputBuffers = outBufs;
357 }
358 mCallback->processCaptureResult(results);
359 freeReleaseFences(results);
360 for (int streamId : streams) {
361 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
362 bb.mDelivered = true;
363 bb.mBuffers.clear();
364 }
365}
366
367void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
368 std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
369 if (lastPartialResultIdx <= batch->mPartialResultProgress) {
370 // Result has been delivered. Return
371 ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
372 return;
373 }
374
375 std::vector<CaptureResult> results;
376 std::vector<uint32_t> toBeRemovedIdxes;
377 for (auto& pair : batch->mResultMds) {
378 uint32_t partialIdx = pair.first;
379 if (partialIdx > lastPartialResultIdx) {
380 continue;
381 }
382 toBeRemovedIdxes.push_back(partialIdx);
383 InflightBatch::MetadataBatch& mb = pair.second;
384 for (const auto& p : mb.mMds) {
385 CaptureResult result;
386 result.frameNumber = p.first;
387 result.result = std::move(p.second);
388 result.inputBuffer.streamId = -1;
389 result.inputBuffer.bufferId = 0;
390 result.inputBuffer.buffer = nullptr;
391 result.partialResult = partialIdx;
392 results.push_back(std::move(result));
393 }
394 mb.mMds.clear();
395 }
396 mCallback->processCaptureResult(results);
397 batch->mPartialResultProgress = lastPartialResultIdx;
398 for (uint32_t partialIdx : toBeRemovedIdxes) {
399 batch->mResultMds.erase(partialIdx);
400 }
401}
402
403void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
404 mCallback->notify({msg});
405 return;
406}
407
408void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
409 uint32_t frameNumber;
410 if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
411 frameNumber = msg.msg.shutter.frameNumber;
412 } else {
413 frameNumber = msg.msg.error.frameNumber;
414 }
415
416 auto pair = getBatch(frameNumber);
417 int batchIdx = pair.first;
418 if (batchIdx == NOT_BATCHED) {
419 notifySingleMsg(msg);
420 return;
421 }
422
423 // When error happened, stop batching for all batches earlier
424 if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
425 Mutex::Autolock _l(mLock);
426 for (int i = 0; i <= batchIdx; i++) {
427 // Send batched data up
428 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
429 {
430 Mutex::Autolock _l(batch->mLock);
431 sendBatchShutterCbsLocked(batch);
432 sendBatchBuffersLocked(batch);
433 sendBatchMetadataLocked(batch, mNumPartialResults);
434 if (!batch->allDelivered()) {
435 ALOGE("%s: error: some batch data not sent back to framework!",
436 __FUNCTION__);
437 }
438 batch->mRemoved = true;
439 }
440 mInflightBatches.pop_front();
441 }
442 // Send the error up
443 notifySingleMsg(msg);
444 return;
445 }
446 // Queue shutter callbacks for future delivery
447 std::shared_ptr<InflightBatch> batch = pair.second;
448 {
449 Mutex::Autolock _l(batch->mLock);
450 // Check if the batch is removed (mostly by notify error) before lock was acquired
451 if (batch->mRemoved) {
452 // Fall back to non-batch path
453 notifySingleMsg(msg);
454 return;
455 }
456
457 batch->mShutterMsgs.push_back(msg);
458 if (frameNumber == batch->mLastFrame) {
459 sendBatchShutterCbsLocked(batch);
460 }
461 } // end of batch lock scope
462
463 // see if the batch is complete
464 if (frameNumber == batch->mLastFrame) {
465 checkAndRemoveFirstBatch();
466 }
467}
468
469void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
470 hidl_vec<CaptureResult> results = {result};
471 mCallback->processCaptureResult(results);
472 freeReleaseFences(results);
473 return;
474}
475
476void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
477 auto pair = getBatch(result.frameNumber);
478 int batchIdx = pair.first;
479 if (batchIdx == NOT_BATCHED) {
480 processOneCaptureResult(result);
481 return;
482 }
483 std::shared_ptr<InflightBatch> batch = pair.second;
484 {
485 Mutex::Autolock _l(batch->mLock);
486 // Check if the batch is removed (mostly by notify error) before lock was acquired
487 if (batch->mRemoved) {
488 // Fall back to non-batch path
489 processOneCaptureResult(result);
490 return;
491 }
492
493 // queue metadata
494 if (result.result.size() != 0) {
495 // Save a copy of metadata
496 batch->mResultMds[result.partialResult].mMds.push_back(
497 std::make_pair(result.frameNumber, result.result));
498 }
499
500 // queue buffer
501 std::vector<int> filledStreams;
502 std::vector<StreamBuffer> nonBatchedBuffers;
503 for (auto& buffer : result.outputBuffers) {
504 auto it = batch->mBatchBufs.find(buffer.streamId);
505 if (it != batch->mBatchBufs.end()) {
506 InflightBatch::BufferBatch& bb = it->second;
507 bb.mBuffers.push_back(buffer);
508 filledStreams.push_back(buffer.streamId);
509 } else {
510 nonBatchedBuffers.push_back(buffer);
511 }
512 }
513
514 // send non-batched buffers up
515 if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
516 CaptureResult nonBatchedResult;
517 nonBatchedResult.frameNumber = result.frameNumber;
518 nonBatchedResult.outputBuffers = nonBatchedBuffers;
519 nonBatchedResult.inputBuffer = result.inputBuffer;
520 nonBatchedResult.partialResult = 0; // 0 for buffer only results
521 processOneCaptureResult(nonBatchedResult);
522 }
523
524 if (result.frameNumber == batch->mLastFrame) {
525 // Send data up
526 if (result.partialResult > 0) {
527 sendBatchMetadataLocked(batch, result.partialResult);
528 }
529 // send buffer up
530 if (filledStreams.size() > 0) {
531 sendBatchBuffersLocked(batch, filledStreams);
532 }
533 }
534 } // end of batch lock scope
535
536 // see if the batch is complete
537 if (result.frameNumber == batch->mLastFrame) {
538 checkAndRemoveFirstBatch();
539 }
540}
541
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700542// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
543Return<void> CameraDeviceSession::constructDefaultRequestSettings(
544 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
545 Status status = initStatus();
546 CameraMetadata outMetadata;
547 const camera_metadata_t *rawRequest;
548 if (status == Status::OK) {
549 ATRACE_BEGIN("camera3->construct_default_request_settings");
550 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
551 ATRACE_END();
552 if (rawRequest == nullptr) {
553 ALOGI("%s: template %d is not supported on this camera device",
554 __FUNCTION__, type);
555 status = Status::ILLEGAL_ARGUMENT;
556 } else {
557 convertToHidl(rawRequest, &outMetadata);
558 }
559 }
560 _hidl_cb(status, outMetadata);
561 return Void();
562}
563
564Return<void> CameraDeviceSession::configureStreams(
565 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
566 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800567 HalStreamConfiguration outStreams;
568
569 // hold the inflight lock for entire configureStreams scope since there must not be any
570 // inflight request/results during stream configuration.
571 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700572 if (!mInflightBuffers.empty()) {
573 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
574 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800575 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
576 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700577 }
578
Emilian Peev98014ff2017-02-02 16:20:12 +0000579 if (status != Status::OK) {
580 _hidl_cb(status, outStreams);
581 return Void();
582 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800583
Emilian Peev98014ff2017-02-02 16:20:12 +0000584 camera3_stream_configuration_t stream_list;
585 hidl_vec<camera3_stream_t*> streams;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800586
Emilian Peev98014ff2017-02-02 16:20:12 +0000587 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
588 stream_list.num_streams = requestedConfiguration.streams.size();
589 streams.resize(stream_list.num_streams);
590 stream_list.streams = streams.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700591
Emilian Peev98014ff2017-02-02 16:20:12 +0000592 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
593 int id = requestedConfiguration.streams[i].id;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700594
Emilian Peev98014ff2017-02-02 16:20:12 +0000595 if (mStreamMap.count(id) == 0) {
596 Camera3Stream stream;
597 convertFromHidl(requestedConfiguration.streams[i], &stream);
598 mStreamMap[id] = stream;
599 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
600 } else {
601 // width/height/format must not change, but usage/rotation might need to change
602 if (mStreamMap[id].stream_type !=
603 (int) requestedConfiguration.streams[i].streamType ||
604 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
605 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
606 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
607 mStreamMap[id].data_space != (android_dataspace_t)
608 requestedConfiguration.streams[i].dataSpace) {
609 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
610 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
611 return Void();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800612 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000613 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
Yin-Chia Yehc25c54f2017-04-04 13:00:35 -0700614 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700615 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000616 streams[i] = &mStreamMap[id];
617 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700618
Emilian Peev98014ff2017-02-02 16:20:12 +0000619 ATRACE_BEGIN("camera3->configure_streams");
620 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
621 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700622
Emilian Peev98014ff2017-02-02 16:20:12 +0000623 // In case Hal returns error most likely it was not able to release
624 // the corresponding resources of the deleted streams.
625 if (ret == OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800626 // delete unused streams, note we do this after adding new streams to ensure new stream
627 // will not have the same address as deleted stream, and HAL has a chance to reference
628 // the to be deleted stream in configure_streams call
629 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
630 int id = it->first;
631 bool found = false;
632 for (const auto& stream : requestedConfiguration.streams) {
633 if (id == stream.id) {
634 found = true;
635 break;
636 }
637 }
638 if (!found) {
639 // Unmap all buffers of deleted stream
Emilian Peev98014ff2017-02-02 16:20:12 +0000640 // in case the configuration call succeeds and HAL
641 // is able to release the corresponding resources too.
642 cleanupBuffersLocked(id);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800643 it = mStreamMap.erase(it);
644 } else {
645 ++it;
646 }
647 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800648
649 // Track video streams
650 mVideoStreamIds.clear();
651 for (const auto& stream : requestedConfiguration.streams) {
652 if (stream.streamType == StreamType::OUTPUT &&
653 stream.usage & graphics::allocator::V2_0::ConsumerUsage::VIDEO_ENCODER) {
654 mVideoStreamIds.push_back(stream.id);
655 }
656 }
657 mResultBatcher.setBatchedStreams(mVideoStreamIds);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700658 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000659
660 if (ret == -EINVAL) {
661 status = Status::ILLEGAL_ARGUMENT;
662 } else if (ret != OK) {
663 status = Status::INTERNAL_ERROR;
664 } else {
665 convertToHidl(stream_list, &outStreams);
666 }
667
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700668 _hidl_cb(status, outStreams);
669 return Void();
670}
671
Emilian Peev98014ff2017-02-02 16:20:12 +0000672// Needs to get called after acquiring 'mInflightLock'
673void CameraDeviceSession::cleanupBuffersLocked(int id) {
674 for (auto& pair : mCirculatingBuffers.at(id)) {
675 sHandleImporter.freeBuffer(pair.second);
676 }
677 mCirculatingBuffers[id].clear();
678 mCirculatingBuffers.erase(id);
679}
680
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700681void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
682 Mutex::Autolock _l(mInflightLock);
683 for (auto& cache : cachesToRemove) {
684 auto cbsIt = mCirculatingBuffers.find(cache.streamId);
685 if (cbsIt == mCirculatingBuffers.end()) {
686 // The stream could have been removed
687 continue;
688 }
689 CirculatingBuffers& cbs = cbsIt->second;
690 auto it = cbs.find(cache.bufferId);
691 if (it != cbs.end()) {
692 sHandleImporter.freeBuffer(it->second);
693 cbs.erase(it);
694 } else {
695 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
696 __FUNCTION__, cache.streamId, cache.bufferId);
697 }
698 }
699}
700
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800701Return<void> CameraDeviceSession::processCaptureRequest(
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700702 const hidl_vec<CaptureRequest>& requests,
703 const hidl_vec<BufferCache>& cachesToRemove,
704 processCaptureRequest_cb _hidl_cb) {
705 updateBufferCaches(cachesToRemove);
706
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800707 uint32_t numRequestProcessed = 0;
708 Status s = Status::OK;
709 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
710 s = processOneCaptureRequest(requests[i]);
711 if (s != Status::OK) {
712 break;
713 }
714 }
715
716 if (s == Status::OK && requests.size() > 1) {
717 mResultBatcher.registerBatch(requests);
718 }
719
720 _hidl_cb(s, numRequestProcessed);
721 return Void();
722}
723
724Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700725 Status status = initStatus();
726 if (status != Status::OK) {
727 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
728 return status;
729 }
730
731 camera3_capture_request_t halRequest;
732 halRequest.frame_number = request.frameNumber;
733 bool converted = convertFromHidl(request.settings, &halRequest.settings);
734 if (!converted) {
735 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
736 return Status::INTERNAL_ERROR;
737 }
738
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800739 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700740 hidl_vec<int> allFences;
741 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800742 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700743 size_t numOutputBufs = request.outputBuffers.size();
744 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800745 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700746 if (status != Status::OK) {
747 return status;
748 }
749
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700750 hidl_vec<camera3_stream_buffer_t> outHalBufs;
751 outHalBufs.resize(numOutputBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800752 {
753 Mutex::Autolock _l(mInflightLock);
754 if (hasInputBuf) {
755 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
756 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
757 convertFromHidl(
758 allBufPtrs[numOutputBufs], request.inputBuffer.status,
759 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
760 &bufCache);
761 halRequest.input_buffer = &bufCache;
762 } else {
763 halRequest.input_buffer = nullptr;
764 }
765
766 halRequest.num_output_buffers = numOutputBufs;
767 for (size_t i = 0; i < numOutputBufs; i++) {
768 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
769 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
770 convertFromHidl(
771 allBufPtrs[i], request.outputBuffers[i].status,
772 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
773 &bufCache);
774 outHalBufs[i] = bufCache;
775 }
776 halRequest.output_buffers = outHalBufs.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700777 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700778
779 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
780 ATRACE_BEGIN("camera3->process_capture_request");
781 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
782 ATRACE_END();
783 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800784 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700785 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
786
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800787 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700788 if (hasInputBuf) {
789 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
790 mInflightBuffers.erase(key);
791 }
792 for (size_t i = 0; i < numOutputBufs; i++) {
793 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
794 mInflightBuffers.erase(key);
795 }
796 return Status::INTERNAL_ERROR;
797 }
798
799 return Status::OK;
800}
801
802Return<Status> CameraDeviceSession::flush() {
803 Status status = initStatus();
804 if (status == Status::OK) {
805 // Flush is always supported on device 3.1 or later
806 status_t ret = mDevice->ops->flush(mDevice);
807 if (ret != OK) {
808 status = Status::INTERNAL_ERROR;
809 }
810 }
811 return status;
812}
813
814Return<void> CameraDeviceSession::close() {
815 Mutex::Autolock _l(mStateLock);
816 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800817 {
818 Mutex::Autolock _l(mInflightLock);
819 if (!mInflightBuffers.empty()) {
820 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
821 __FUNCTION__, mInflightBuffers.size());
822 }
823 }
824
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700825 ATRACE_BEGIN("camera3->close");
826 mDevice->common.close(&mDevice->common);
827 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800828
829 // free all imported buffers
830 for(auto& pair : mCirculatingBuffers) {
831 CirculatingBuffers& buffers = pair.second;
832 for (auto& p2 : buffers) {
833 sHandleImporter.freeBuffer(p2.second);
834 }
835 }
836
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700837 mClosed = true;
838 }
839 return Void();
840}
841
842/**
843 * Static callback forwarding methods from HAL to instance
844 */
845void CameraDeviceSession::sProcessCaptureResult(
846 const camera3_callback_ops *cb,
847 const camera3_capture_result *hal_result) {
848 CameraDeviceSession *d =
849 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
850
851 uint32_t frameNumber = hal_result->frame_number;
852 bool hasInputBuf = (hal_result->input_buffer != nullptr);
853 size_t numOutputBufs = hal_result->num_output_buffers;
854 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800855 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800856 Mutex::Autolock _l(d->mInflightLock);
857 if (hasInputBuf) {
858 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
859 // validate if buffer is inflight
860 auto key = std::make_pair(streamId, frameNumber);
861 if (d->mInflightBuffers.count(key) != 1) {
862 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
863 __FUNCTION__, streamId, frameNumber);
864 return;
865 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700866 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700867
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800868 for (size_t i = 0; i < numOutputBufs; i++) {
869 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
870 // validate if buffer is inflight
871 auto key = std::make_pair(streamId, frameNumber);
872 if (d->mInflightBuffers.count(key) != 1) {
873 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
874 __FUNCTION__, streamId, frameNumber);
875 return;
876 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700877 }
878 }
879 // We don't need to validate/import fences here since we will be passing them to camera service
880 // within the scope of this function
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700881 CaptureResult result;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700882 result.frameNumber = frameNumber;
883 result.partialResult = hal_result->partial_result;
884 convertToHidl(hal_result->result, &result.result);
885 if (hasInputBuf) {
886 result.inputBuffer.streamId =
887 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
888 result.inputBuffer.buffer = nullptr;
889 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
890 // skip acquire fence since it's no use to camera service
891 if (hal_result->input_buffer->release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800892 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
893 handle->data[0] = hal_result->input_buffer->release_fence;
894 result.inputBuffer.releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800895 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800896 result.inputBuffer.releaseFence = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700897 }
898 } else {
899 result.inputBuffer.streamId = -1;
900 }
901
902 result.outputBuffers.resize(numOutputBufs);
903 for (size_t i = 0; i < numOutputBufs; i++) {
904 result.outputBuffers[i].streamId =
905 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
906 result.outputBuffers[i].buffer = nullptr;
907 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
908 // skip acquire fence since it's of no use to camera service
909 if (hal_result->output_buffers[i].release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800910 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
911 handle->data[0] = hal_result->output_buffers[i].release_fence;
912 result.outputBuffers[i].releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800913 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800914 result.outputBuffers[i].releaseFence = nullptr;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800915 }
916 }
917
918 // Free inflight record/fences.
919 // Do this before call back to camera service because camera service might jump to
920 // configure_streams right after the processCaptureResult call so we need to finish
921 // updating inflight queues first
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800922 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800923 Mutex::Autolock _l(d->mInflightLock);
924 if (hasInputBuf) {
925 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
926 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800927 d->mInflightBuffers.erase(key);
928 }
929
930 for (size_t i = 0; i < numOutputBufs; i++) {
931 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
932 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800933 d->mInflightBuffers.erase(key);
934 }
935
936 if (d->mInflightBuffers.empty()) {
937 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700938 }
939 }
940
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800941 d->mResultBatcher.processCaptureResult(result);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700942}
943
944void CameraDeviceSession::sNotify(
945 const camera3_callback_ops *cb,
946 const camera3_notify_msg *msg) {
947 CameraDeviceSession *d =
948 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
949 NotifyMsg hidlMsg;
950 convertToHidl(msg, &hidlMsg);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800951
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800952 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
953 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700954 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
955 ALOGE("%s: unknown stream ID %d reports an error!",
956 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800957 return;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700958 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700959 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800960 d->mResultBatcher.notify(hidlMsg);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700961}
962
963} // namespace implementation
964} // namespace V3_2
965} // namespace device
966} // namespace camera
967} // namespace hardware
968} // namespace android