blob: e9f78ff3996e342946481c83922cd5ac92f90ebd [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
Yifan Hong1192e1d2017-04-11 14:45:00 -070033// Size of request metadata fast message queue. Change to 0 to always use hwbinder buffer.
34static constexpr size_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1MB */;
Yifan Hong993e3d02017-04-12 16:31:23 -070035// Size of result metadata fast message queue. Change to 0 to always use hwbinder buffer.
36static constexpr size_t CAMERA_RESULT_METADATA_QUEUE_SIZE = 1 << 20 /* 1MB */;
Yifan Hong1192e1d2017-04-11 14:45:00 -070037
Yin-Chia Yeh248ed702017-01-23 17:27:26 -080038HandleImporter& CameraDeviceSession::sHandleImporter = HandleImporter::getInstance();
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080039const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070040
41CameraDeviceSession::CameraDeviceSession(
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080042 camera3_device_t* device,
43 const camera_metadata_t* deviceInfo,
44 const sp<ICameraDeviceCallback>& callback) :
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070045 camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
46 mDevice(device),
Emilian Peev7d52a6f2017-04-07 09:53:48 +010047 mDeviceVersion(device->common.version),
Emilian Peevcf581372017-04-07 13:53:10 +010048 mIsAELockAvailable(false),
49 mNumPartialResults(1),
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080050 mResultBatcher(callback) {
51
52 mDeviceInfo = deviceInfo;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080053 camera_metadata_entry partialResultsCount =
54 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
55 if (partialResultsCount.count > 0) {
Emilian Peevcf581372017-04-07 13:53:10 +010056 mNumPartialResults = partialResultsCount.data.i32[0];
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080057 }
Emilian Peevcf581372017-04-07 13:53:10 +010058 mResultBatcher.setNumPartialResults(mNumPartialResults);
59
60 camera_metadata_entry aeLockAvailableEntry = mDeviceInfo.find(
61 ANDROID_CONTROL_AE_LOCK_AVAILABLE);
62 if (aeLockAvailableEntry.count > 0) {
63 mIsAELockAvailable = (aeLockAvailableEntry.data.u8[0] ==
64 ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
65 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080066
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070067 mInitFail = initialize();
68}
69
70bool CameraDeviceSession::initialize() {
71 /** Initialize device with callback functions */
72 ATRACE_BEGIN("camera3->initialize");
73 status_t res = mDevice->ops->initialize(mDevice, this);
74 ATRACE_END();
75
76 if (res != OK) {
77 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
78 __FUNCTION__, strerror(-res), res);
79 mDevice->common.close(&mDevice->common);
80 mClosed = true;
81 return true;
82 }
Yifan Hong1192e1d2017-04-11 14:45:00 -070083
84 mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
85 CAMERA_REQUEST_METADATA_QUEUE_SIZE, false /* non blocking */);
86 if (!mRequestMetadataQueue->isValid()) {
Yifan Hong993e3d02017-04-12 16:31:23 -070087 ALOGE("%s: invalid request fmq", __FUNCTION__);
Yifan Hong1192e1d2017-04-11 14:45:00 -070088 return true;
89 }
Yifan Hong993e3d02017-04-12 16:31:23 -070090 mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
91 CAMERA_RESULT_METADATA_QUEUE_SIZE, false /* non blocking */);
92 if (!mResultMetadataQueue->isValid()) {
93 ALOGE("%s: invalid result fmq", __FUNCTION__);
94 return true;
95 }
96 mResultBatcher.setResultMetadataQueue(mResultMetadataQueue);
Yifan Hong1192e1d2017-04-11 14:45:00 -070097
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070098 return false;
99}
100
101CameraDeviceSession::~CameraDeviceSession() {
102 if (!isClosed()) {
103 ALOGE("CameraDeviceSession deleted before close!");
104 close();
105 }
106}
107
108bool CameraDeviceSession::isClosed() {
109 Mutex::Autolock _l(mStateLock);
110 return mClosed;
111}
112
113Status CameraDeviceSession::initStatus() const {
114 Mutex::Autolock _l(mStateLock);
115 Status status = Status::OK;
116 if (mInitFail) {
117 status = Status::INTERNAL_ERROR;
118 } else if (mDisconnected) {
119 status = Status::CAMERA_DISCONNECTED;
120 } else if (mClosed) {
121 status = Status::INTERNAL_ERROR;
122 }
123 return status;
124}
125
126void CameraDeviceSession::disconnect() {
127 Mutex::Autolock _l(mStateLock);
128 mDisconnected = true;
129 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
130 if (!mClosed) {
131 mDevice->common.close(&mDevice->common);
132 mClosed = true;
133 }
134}
135
136void CameraDeviceSession::dumpState(const native_handle_t* fd) {
137 if (!isClosed()) {
138 mDevice->ops->dump(mDevice, fd->data[0]);
139 }
140}
141
Emilian Peevcf581372017-04-07 13:53:10 +0100142/**
143 * For devices <= CAMERA_DEVICE_API_VERSION_3_2, AE_PRECAPTURE_TRIGGER_CANCEL is not supported so
144 * we need to override AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE and AE_LOCK_OFF
145 * to AE_LOCK_ON to start cancelling AE precapture. If AE lock is not available, it still overrides
146 * AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE but doesn't add AE_LOCK_ON to the
147 * request.
148 */
149bool CameraDeviceSession::handleAePrecaptureCancelRequestLocked(
150 const camera3_capture_request_t &halRequest,
151 ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/,
152 AETriggerCancelOverride *override /*out*/) {
153 if ((mDeviceVersion > CAMERA_DEVICE_API_VERSION_3_2) ||
154 (nullptr == halRequest.settings) || (nullptr == settings) ||
155 (0 == get_camera_metadata_entry_count(halRequest.settings))) {
156 return false;
157 }
158
159 settings->clear();
160 settings->append(halRequest.settings);
161 camera_metadata_entry_t aePrecaptureTrigger =
162 settings->find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
163 if (aePrecaptureTrigger.count > 0 &&
164 aePrecaptureTrigger.data.u8[0] ==
165 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL) {
166 // Always override CANCEL to IDLE
167 uint8_t aePrecaptureTrigger =
168 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
169 settings->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
170 &aePrecaptureTrigger, 1);
171 *override = { false, ANDROID_CONTROL_AE_LOCK_OFF,
172 true, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL };
173
174 if (mIsAELockAvailable == true) {
175 camera_metadata_entry_t aeLock = settings->find(
176 ANDROID_CONTROL_AE_LOCK);
177 if (aeLock.count == 0 || aeLock.data.u8[0] ==
178 ANDROID_CONTROL_AE_LOCK_OFF) {
179 uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_ON;
180 settings->update(ANDROID_CONTROL_AE_LOCK, &aeLock, 1);
181 override->applyAeLock = true;
182 override->aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
183 }
184 }
185
186 return true;
187 }
188
189 return false;
190}
191
192/**
193 * Override result metadata for cancelling AE precapture trigger applied in
194 * handleAePrecaptureCancelRequestLocked().
195 */
196void CameraDeviceSession::overrideResultForPrecaptureCancelLocked(
197 const AETriggerCancelOverride &aeTriggerCancelOverride,
198 ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/) {
199 if (aeTriggerCancelOverride.applyAeLock) {
200 // Only devices <= v3.2 should have this override
201 assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
202 settings->update(ANDROID_CONTROL_AE_LOCK, &aeTriggerCancelOverride.aeLock, 1);
203 }
204
205 if (aeTriggerCancelOverride.applyAePrecaptureTrigger) {
206 // Only devices <= v3.2 should have this override
207 assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
208 settings->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
209 &aeTriggerCancelOverride.aePrecaptureTrigger, 1);
210 }
211}
212
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700213Status CameraDeviceSession::importRequest(
214 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800215 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700216 hidl_vec<int>& allFences) {
217 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800218 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700219 size_t numOutputBufs = request.outputBuffers.size();
220 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
221 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800222 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800223 hidl_vec<uint64_t> allBufIds;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700224 allBufs.resize(numBufs);
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800225 allBufIds.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800226 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700227 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800228 std::vector<int32_t> streamIds(numBufs);
229
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700230 for (size_t i = 0; i < numOutputBufs; i++) {
231 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800232 allBufIds[i] = request.outputBuffers[i].bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800233 allBufPtrs[i] = &allBufs[i];
234 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700235 }
236 if (hasInputBuf) {
237 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800238 allBufIds[numOutputBufs] = request.inputBuffer.bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800239 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
240 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700241 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800242
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700243 for (size_t i = 0; i < numBufs; i++) {
244 buffer_handle_t buf = allBufs[i];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800245 uint64_t bufId = allBufIds[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800246 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800247 if (cbs.count(bufId) == 0) {
248 if (buf == nullptr) {
249 ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
250 return Status::ILLEGAL_ARGUMENT;
251 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800252 // Register a newly seen buffer
253 buffer_handle_t importedBuf = buf;
254 sHandleImporter.importBuffer(importedBuf);
255 if (importedBuf == nullptr) {
256 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
257 return Status::INTERNAL_ERROR;
258 } else {
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800259 cbs[bufId] = importedBuf;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800260 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700261 }
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800262 allBufPtrs[i] = &cbs[bufId];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700263 }
264
265 // All buffers are imported. Now validate output buffer acquire fences
266 for (size_t i = 0; i < numOutputBufs; i++) {
267 if (!sHandleImporter.importFence(
268 request.outputBuffers[i].acquireFence, allFences[i])) {
269 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800270 cleanupInflightFences(allFences, i);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700271 return Status::INTERNAL_ERROR;
272 }
273 }
274
275 // Validate input buffer acquire fences
276 if (hasInputBuf) {
277 if (!sHandleImporter.importFence(
278 request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
279 ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800280 cleanupInflightFences(allFences, numOutputBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700281 return Status::INTERNAL_ERROR;
282 }
283 }
284 return Status::OK;
285}
286
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800287void CameraDeviceSession::cleanupInflightFences(
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700288 hidl_vec<int>& allFences, size_t numFences) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700289 for (size_t j = 0; j < numFences; j++) {
290 sHandleImporter.closeFence(allFences[j]);
291 }
292}
293
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800294CameraDeviceSession::ResultBatcher::ResultBatcher(
295 const sp<ICameraDeviceCallback>& callback) : mCallback(callback) {};
296
297bool CameraDeviceSession::ResultBatcher::InflightBatch::allDelivered() const {
298 if (!mShutterDelivered) return false;
299
300 if (mPartialResultProgress < mNumPartialResults) {
301 return false;
302 }
303
304 for (const auto& pair : mBatchBufs) {
305 if (!pair.second.mDelivered) {
306 return false;
307 }
308 }
309 return true;
310}
311
312void CameraDeviceSession::ResultBatcher::setNumPartialResults(uint32_t n) {
313 Mutex::Autolock _l(mLock);
314 mNumPartialResults = n;
315}
316
317void CameraDeviceSession::ResultBatcher::setBatchedStreams(
318 const std::vector<int>& streamsToBatch) {
319 Mutex::Autolock _l(mLock);
320 mStreamsToBatch = streamsToBatch;
321}
322
Yifan Hong993e3d02017-04-12 16:31:23 -0700323void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q) {
324 Mutex::Autolock _l(mLock);
325 mResultMetadataQueue = q;
326}
327
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800328void CameraDeviceSession::ResultBatcher::registerBatch(
329 const hidl_vec<CaptureRequest>& requests) {
330 auto batch = std::make_shared<InflightBatch>();
331 batch->mFirstFrame = requests[0].frameNumber;
332 batch->mBatchSize = requests.size();
333 batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
334 batch->mNumPartialResults = mNumPartialResults;
335 for (int id : mStreamsToBatch) {
336 batch->mBatchBufs[id] = InflightBatch::BufferBatch();
337 }
338 Mutex::Autolock _l(mLock);
339 mInflightBatches.push_back(batch);
340}
341
342std::pair<int, std::shared_ptr<CameraDeviceSession::ResultBatcher::InflightBatch>>
343CameraDeviceSession::ResultBatcher::getBatch(
344 uint32_t frameNumber) {
345 Mutex::Autolock _l(mLock);
346 int numBatches = mInflightBatches.size();
347 if (numBatches == 0) {
348 return std::make_pair(NOT_BATCHED, nullptr);
349 }
350 uint32_t frameMin = mInflightBatches[0]->mFirstFrame;
351 uint32_t frameMax = mInflightBatches[numBatches - 1]->mLastFrame;
352 if (frameNumber < frameMin || frameNumber > frameMax) {
353 return std::make_pair(NOT_BATCHED, nullptr);
354 }
355 for (int i = 0; i < numBatches; i++) {
356 if (frameNumber >= mInflightBatches[i]->mFirstFrame &&
357 frameNumber <= mInflightBatches[i]->mLastFrame) {
358 return std::make_pair(i, mInflightBatches[i]);
359 }
360 }
361 return std::make_pair(NOT_BATCHED, nullptr);
362}
363
364void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
365 Mutex::Autolock _l(mLock);
366 if (mInflightBatches.size() > 0) {
367 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
368 bool shouldRemove = false;
369 {
370 Mutex::Autolock _l(batch->mLock);
371 if (batch->allDelivered()) {
372 batch->mRemoved = true;
373 shouldRemove = true;
374 }
375 }
376 if (shouldRemove) {
377 mInflightBatches.pop_front();
378 }
379 }
380}
381
382void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch) {
383 if (batch->mShutterDelivered) {
384 ALOGW("%s: batch shutter callback already sent!", __FUNCTION__);
385 return;
386 }
387
388 mCallback->notify(batch->mShutterMsgs);
389 batch->mShutterDelivered = true;
390 batch->mShutterMsgs.clear();
391}
392
393void CameraDeviceSession::ResultBatcher::freeReleaseFences(hidl_vec<CaptureResult>& results) {
394 for (auto& result : results) {
395 if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
396 native_handle_t* handle = const_cast<native_handle_t*>(
397 result.inputBuffer.releaseFence.getNativeHandle());
398 native_handle_delete(handle);
399 }
400 for (auto& buf : result.outputBuffers) {
401 if (buf.releaseFence.getNativeHandle() != nullptr) {
402 native_handle_t* handle = const_cast<native_handle_t*>(
403 buf.releaseFence.getNativeHandle());
404 native_handle_delete(handle);
405 }
406 }
407 }
408 return;
409}
410
411void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
412 sendBatchBuffersLocked(batch, mStreamsToBatch);
413}
414
415void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
416 std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
417 size_t batchSize = 0;
418 for (int streamId : streams) {
419 auto it = batch->mBatchBufs.find(streamId);
420 if (it != batch->mBatchBufs.end()) {
421 InflightBatch::BufferBatch& bb = it->second;
422 if (bb.mDelivered) {
423 continue;
424 }
425 if (bb.mBuffers.size() > batchSize) {
426 batchSize = bb.mBuffers.size();
427 }
428 } else {
429 ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
430 return;
431 }
432 }
433
434 if (batchSize == 0) {
435 ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
436 for (int streamId : streams) {
437 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
438 bb.mDelivered = true;
439 }
440 return;
441 }
442
443 hidl_vec<CaptureResult> results;
444 results.resize(batchSize);
445 for (size_t i = 0; i < batchSize; i++) {
446 results[i].frameNumber = batch->mFirstFrame + i;
Yifan Hong993e3d02017-04-12 16:31:23 -0700447 results[i].fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800448 results[i].partialResult = 0; // 0 for buffer only results
449 results[i].inputBuffer.streamId = -1;
450 results[i].inputBuffer.bufferId = 0;
451 results[i].inputBuffer.buffer = nullptr;
452 std::vector<StreamBuffer> outBufs;
453 for (int streamId : streams) {
454 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
455 if (bb.mDelivered) {
456 continue;
457 }
458 if (i < bb.mBuffers.size()) {
459 outBufs.push_back(bb.mBuffers[i]);
460 }
461 }
462 results[i].outputBuffers = outBufs;
463 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700464 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */false);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800465 freeReleaseFences(results);
466 for (int streamId : streams) {
467 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
468 bb.mDelivered = true;
469 bb.mBuffers.clear();
470 }
471}
472
473void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
474 std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
475 if (lastPartialResultIdx <= batch->mPartialResultProgress) {
476 // Result has been delivered. Return
477 ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
478 return;
479 }
480
481 std::vector<CaptureResult> results;
482 std::vector<uint32_t> toBeRemovedIdxes;
483 for (auto& pair : batch->mResultMds) {
484 uint32_t partialIdx = pair.first;
485 if (partialIdx > lastPartialResultIdx) {
486 continue;
487 }
488 toBeRemovedIdxes.push_back(partialIdx);
489 InflightBatch::MetadataBatch& mb = pair.second;
490 for (const auto& p : mb.mMds) {
491 CaptureResult result;
492 result.frameNumber = p.first;
493 result.result = std::move(p.second);
Yifan Hong993e3d02017-04-12 16:31:23 -0700494 result.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800495 result.inputBuffer.streamId = -1;
496 result.inputBuffer.bufferId = 0;
497 result.inputBuffer.buffer = nullptr;
498 result.partialResult = partialIdx;
499 results.push_back(std::move(result));
500 }
501 mb.mMds.clear();
502 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700503 hidl_vec<CaptureResult> hResults;
504 hResults.setToExternal(results.data(), results.size());
505 invokeProcessCaptureResultCallback(hResults, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800506 batch->mPartialResultProgress = lastPartialResultIdx;
507 for (uint32_t partialIdx : toBeRemovedIdxes) {
508 batch->mResultMds.erase(partialIdx);
509 }
510}
511
512void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
513 mCallback->notify({msg});
514 return;
515}
516
517void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
518 uint32_t frameNumber;
519 if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
520 frameNumber = msg.msg.shutter.frameNumber;
521 } else {
522 frameNumber = msg.msg.error.frameNumber;
523 }
524
525 auto pair = getBatch(frameNumber);
526 int batchIdx = pair.first;
527 if (batchIdx == NOT_BATCHED) {
528 notifySingleMsg(msg);
529 return;
530 }
531
532 // When error happened, stop batching for all batches earlier
533 if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
534 Mutex::Autolock _l(mLock);
535 for (int i = 0; i <= batchIdx; i++) {
536 // Send batched data up
537 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
538 {
539 Mutex::Autolock _l(batch->mLock);
540 sendBatchShutterCbsLocked(batch);
541 sendBatchBuffersLocked(batch);
542 sendBatchMetadataLocked(batch, mNumPartialResults);
543 if (!batch->allDelivered()) {
544 ALOGE("%s: error: some batch data not sent back to framework!",
545 __FUNCTION__);
546 }
547 batch->mRemoved = true;
548 }
549 mInflightBatches.pop_front();
550 }
551 // Send the error up
552 notifySingleMsg(msg);
553 return;
554 }
555 // Queue shutter callbacks for future delivery
556 std::shared_ptr<InflightBatch> batch = pair.second;
557 {
558 Mutex::Autolock _l(batch->mLock);
559 // Check if the batch is removed (mostly by notify error) before lock was acquired
560 if (batch->mRemoved) {
561 // Fall back to non-batch path
562 notifySingleMsg(msg);
563 return;
564 }
565
566 batch->mShutterMsgs.push_back(msg);
567 if (frameNumber == batch->mLastFrame) {
568 sendBatchShutterCbsLocked(batch);
569 }
570 } // end of batch lock scope
571
572 // see if the batch is complete
573 if (frameNumber == batch->mLastFrame) {
574 checkAndRemoveFirstBatch();
575 }
576}
577
Yifan Hong993e3d02017-04-12 16:31:23 -0700578void CameraDeviceSession::ResultBatcher::invokeProcessCaptureResultCallback(
579 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
580 if (mProcessCaptureResultLock.tryLock() != OK) {
581 ALOGW("%s: previous call is not finished! waiting 1s...",
582 __FUNCTION__);
583 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
584 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
585 __FUNCTION__);
586 return;
587 }
588 }
589 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
590 for (CaptureResult &result : results) {
591 if (result.result.size() > 0) {
592 if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
593 result.fmqResultSize = result.result.size();
594 result.result.resize(0);
595 } else {
596 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
597 result.fmqResultSize = 0;
598 }
599 }
600 }
601 }
602 mCallback->processCaptureResult(results);
603 mProcessCaptureResultLock.unlock();
604}
605
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800606void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
607 hidl_vec<CaptureResult> results = {result};
Yifan Hong993e3d02017-04-12 16:31:23 -0700608 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800609 freeReleaseFences(results);
610 return;
611}
612
613void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
614 auto pair = getBatch(result.frameNumber);
615 int batchIdx = pair.first;
616 if (batchIdx == NOT_BATCHED) {
617 processOneCaptureResult(result);
618 return;
619 }
620 std::shared_ptr<InflightBatch> batch = pair.second;
621 {
622 Mutex::Autolock _l(batch->mLock);
623 // Check if the batch is removed (mostly by notify error) before lock was acquired
624 if (batch->mRemoved) {
625 // Fall back to non-batch path
626 processOneCaptureResult(result);
627 return;
628 }
629
630 // queue metadata
631 if (result.result.size() != 0) {
632 // Save a copy of metadata
633 batch->mResultMds[result.partialResult].mMds.push_back(
634 std::make_pair(result.frameNumber, result.result));
635 }
636
637 // queue buffer
638 std::vector<int> filledStreams;
639 std::vector<StreamBuffer> nonBatchedBuffers;
640 for (auto& buffer : result.outputBuffers) {
641 auto it = batch->mBatchBufs.find(buffer.streamId);
642 if (it != batch->mBatchBufs.end()) {
643 InflightBatch::BufferBatch& bb = it->second;
644 bb.mBuffers.push_back(buffer);
645 filledStreams.push_back(buffer.streamId);
646 } else {
647 nonBatchedBuffers.push_back(buffer);
648 }
649 }
650
651 // send non-batched buffers up
652 if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
653 CaptureResult nonBatchedResult;
654 nonBatchedResult.frameNumber = result.frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -0700655 nonBatchedResult.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800656 nonBatchedResult.outputBuffers = nonBatchedBuffers;
657 nonBatchedResult.inputBuffer = result.inputBuffer;
658 nonBatchedResult.partialResult = 0; // 0 for buffer only results
659 processOneCaptureResult(nonBatchedResult);
660 }
661
662 if (result.frameNumber == batch->mLastFrame) {
663 // Send data up
664 if (result.partialResult > 0) {
665 sendBatchMetadataLocked(batch, result.partialResult);
666 }
667 // send buffer up
668 if (filledStreams.size() > 0) {
669 sendBatchBuffersLocked(batch, filledStreams);
670 }
671 }
672 } // end of batch lock scope
673
674 // see if the batch is complete
675 if (result.frameNumber == batch->mLastFrame) {
676 checkAndRemoveFirstBatch();
677 }
678}
679
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700680// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
681Return<void> CameraDeviceSession::constructDefaultRequestSettings(
682 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
683 Status status = initStatus();
684 CameraMetadata outMetadata;
685 const camera_metadata_t *rawRequest;
686 if (status == Status::OK) {
687 ATRACE_BEGIN("camera3->construct_default_request_settings");
688 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
689 ATRACE_END();
690 if (rawRequest == nullptr) {
691 ALOGI("%s: template %d is not supported on this camera device",
692 __FUNCTION__, type);
693 status = Status::ILLEGAL_ARGUMENT;
694 } else {
695 convertToHidl(rawRequest, &outMetadata);
696 }
697 }
698 _hidl_cb(status, outMetadata);
699 return Void();
700}
701
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100702/**
703 * Map Android N dataspace definitions back to Android M definitions, for
704 * use with HALv3.3 or older.
705 *
706 * Only map where correspondences exist, and otherwise preserve the value.
707 */
708android_dataspace CameraDeviceSession::mapToLegacyDataspace(
709 android_dataspace dataSpace) const {
710 if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
711 switch (dataSpace) {
712 case HAL_DATASPACE_V0_SRGB_LINEAR:
713 return HAL_DATASPACE_SRGB_LINEAR;
714 case HAL_DATASPACE_V0_SRGB:
715 return HAL_DATASPACE_SRGB;
716 case HAL_DATASPACE_V0_JFIF:
717 return HAL_DATASPACE_JFIF;
718 case HAL_DATASPACE_V0_BT601_625:
719 return HAL_DATASPACE_BT601_625;
720 case HAL_DATASPACE_V0_BT601_525:
721 return HAL_DATASPACE_BT601_525;
722 case HAL_DATASPACE_V0_BT709:
723 return HAL_DATASPACE_BT709;
724 default:
725 return dataSpace;
726 }
727 }
728
729 return dataSpace;
730}
731
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700732Return<void> CameraDeviceSession::configureStreams(
733 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
734 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800735 HalStreamConfiguration outStreams;
736
737 // hold the inflight lock for entire configureStreams scope since there must not be any
738 // inflight request/results during stream configuration.
739 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700740 if (!mInflightBuffers.empty()) {
741 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
742 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800743 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
744 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700745 }
746
Emilian Peevcf581372017-04-07 13:53:10 +0100747 if (!mInflightAETriggerOverrides.empty()) {
748 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
749 " trigger overrides!", __FUNCTION__,
750 mInflightAETriggerOverrides.size());
751 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
752 return Void();
753 }
754
Emilian Peev98014ff2017-02-02 16:20:12 +0000755 if (status != Status::OK) {
756 _hidl_cb(status, outStreams);
757 return Void();
758 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800759
Emilian Peev98014ff2017-02-02 16:20:12 +0000760 camera3_stream_configuration_t stream_list;
761 hidl_vec<camera3_stream_t*> streams;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800762
Emilian Peev98014ff2017-02-02 16:20:12 +0000763 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
764 stream_list.num_streams = requestedConfiguration.streams.size();
765 streams.resize(stream_list.num_streams);
766 stream_list.streams = streams.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700767
Emilian Peev98014ff2017-02-02 16:20:12 +0000768 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
769 int id = requestedConfiguration.streams[i].id;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700770
Emilian Peev98014ff2017-02-02 16:20:12 +0000771 if (mStreamMap.count(id) == 0) {
772 Camera3Stream stream;
773 convertFromHidl(requestedConfiguration.streams[i], &stream);
774 mStreamMap[id] = stream;
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100775 mStreamMap[id].data_space = mapToLegacyDataspace(
776 mStreamMap[id].data_space);
Emilian Peev98014ff2017-02-02 16:20:12 +0000777 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
778 } else {
779 // width/height/format must not change, but usage/rotation might need to change
780 if (mStreamMap[id].stream_type !=
781 (int) requestedConfiguration.streams[i].streamType ||
782 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
783 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
784 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100785 mStreamMap[id].data_space !=
786 mapToLegacyDataspace( static_cast<android_dataspace_t> (
787 requestedConfiguration.streams[i].dataSpace))) {
Emilian Peev98014ff2017-02-02 16:20:12 +0000788 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
789 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
790 return Void();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800791 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000792 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
Yin-Chia Yehc25c54f2017-04-04 13:00:35 -0700793 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700794 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000795 streams[i] = &mStreamMap[id];
796 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700797
Emilian Peev98014ff2017-02-02 16:20:12 +0000798 ATRACE_BEGIN("camera3->configure_streams");
799 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
800 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700801
Emilian Peev98014ff2017-02-02 16:20:12 +0000802 // In case Hal returns error most likely it was not able to release
803 // the corresponding resources of the deleted streams.
804 if (ret == OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800805 // delete unused streams, note we do this after adding new streams to ensure new stream
806 // will not have the same address as deleted stream, and HAL has a chance to reference
807 // the to be deleted stream in configure_streams call
808 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
809 int id = it->first;
810 bool found = false;
811 for (const auto& stream : requestedConfiguration.streams) {
812 if (id == stream.id) {
813 found = true;
814 break;
815 }
816 }
817 if (!found) {
818 // Unmap all buffers of deleted stream
Emilian Peev98014ff2017-02-02 16:20:12 +0000819 // in case the configuration call succeeds and HAL
820 // is able to release the corresponding resources too.
821 cleanupBuffersLocked(id);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800822 it = mStreamMap.erase(it);
823 } else {
824 ++it;
825 }
826 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800827
828 // Track video streams
829 mVideoStreamIds.clear();
830 for (const auto& stream : requestedConfiguration.streams) {
831 if (stream.streamType == StreamType::OUTPUT &&
Chia-I Wu79d13ff2017-03-31 12:48:11 -0700832 stream.usage &
833 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800834 mVideoStreamIds.push_back(stream.id);
835 }
836 }
837 mResultBatcher.setBatchedStreams(mVideoStreamIds);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700838 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000839
840 if (ret == -EINVAL) {
841 status = Status::ILLEGAL_ARGUMENT;
842 } else if (ret != OK) {
843 status = Status::INTERNAL_ERROR;
844 } else {
845 convertToHidl(stream_list, &outStreams);
846 }
847
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700848 _hidl_cb(status, outStreams);
849 return Void();
850}
851
Emilian Peev98014ff2017-02-02 16:20:12 +0000852// Needs to get called after acquiring 'mInflightLock'
853void CameraDeviceSession::cleanupBuffersLocked(int id) {
854 for (auto& pair : mCirculatingBuffers.at(id)) {
855 sHandleImporter.freeBuffer(pair.second);
856 }
857 mCirculatingBuffers[id].clear();
858 mCirculatingBuffers.erase(id);
859}
860
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700861void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
862 Mutex::Autolock _l(mInflightLock);
863 for (auto& cache : cachesToRemove) {
864 auto cbsIt = mCirculatingBuffers.find(cache.streamId);
865 if (cbsIt == mCirculatingBuffers.end()) {
866 // The stream could have been removed
867 continue;
868 }
869 CirculatingBuffers& cbs = cbsIt->second;
870 auto it = cbs.find(cache.bufferId);
871 if (it != cbs.end()) {
872 sHandleImporter.freeBuffer(it->second);
873 cbs.erase(it);
874 } else {
875 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
876 __FUNCTION__, cache.streamId, cache.bufferId);
877 }
878 }
879}
880
Yifan Hong1192e1d2017-04-11 14:45:00 -0700881Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
882 getCaptureRequestMetadataQueue_cb _hidl_cb) {
883 _hidl_cb(*mRequestMetadataQueue->getDesc());
884 return Void();
885}
886
Yifan Hong993e3d02017-04-12 16:31:23 -0700887Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
888 getCaptureResultMetadataQueue_cb _hidl_cb) {
889 _hidl_cb(*mResultMetadataQueue->getDesc());
890 return Void();
891}
892
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800893Return<void> CameraDeviceSession::processCaptureRequest(
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700894 const hidl_vec<CaptureRequest>& requests,
895 const hidl_vec<BufferCache>& cachesToRemove,
896 processCaptureRequest_cb _hidl_cb) {
897 updateBufferCaches(cachesToRemove);
898
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800899 uint32_t numRequestProcessed = 0;
900 Status s = Status::OK;
901 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
902 s = processOneCaptureRequest(requests[i]);
903 if (s != Status::OK) {
904 break;
905 }
906 }
907
908 if (s == Status::OK && requests.size() > 1) {
909 mResultBatcher.registerBatch(requests);
910 }
911
912 _hidl_cb(s, numRequestProcessed);
913 return Void();
914}
915
916Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700917 Status status = initStatus();
918 if (status != Status::OK) {
919 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
920 return status;
921 }
922
923 camera3_capture_request_t halRequest;
924 halRequest.frame_number = request.frameNumber;
Yifan Hong1192e1d2017-04-11 14:45:00 -0700925
926 bool converted = true;
927 CameraMetadata settingsFmq; // settings from FMQ
928 if (request.fmqSettingsSize > 0) {
929 // non-blocking read; client must write metadata before calling
930 // processOneCaptureRequest
931 settingsFmq.resize(request.fmqSettingsSize);
932 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
933 if (read) {
934 converted = convertFromHidl(settingsFmq, &halRequest.settings);
935 } else {
936 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
937 converted = false;
938 }
939 } else {
940 converted = convertFromHidl(request.settings, &halRequest.settings);
941 }
942
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700943 if (!converted) {
944 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
945 return Status::INTERNAL_ERROR;
946 }
947
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800948 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700949 hidl_vec<int> allFences;
950 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800951 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700952 size_t numOutputBufs = request.outputBuffers.size();
953 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800954 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700955 if (status != Status::OK) {
956 return status;
957 }
958
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700959 hidl_vec<camera3_stream_buffer_t> outHalBufs;
960 outHalBufs.resize(numOutputBufs);
Emilian Peevcf581372017-04-07 13:53:10 +0100961 bool aeCancelTriggerNeeded = false;
962 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800963 {
964 Mutex::Autolock _l(mInflightLock);
965 if (hasInputBuf) {
966 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
967 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
968 convertFromHidl(
969 allBufPtrs[numOutputBufs], request.inputBuffer.status,
970 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
971 &bufCache);
972 halRequest.input_buffer = &bufCache;
973 } else {
974 halRequest.input_buffer = nullptr;
975 }
976
977 halRequest.num_output_buffers = numOutputBufs;
978 for (size_t i = 0; i < numOutputBufs; i++) {
979 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
980 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
981 convertFromHidl(
982 allBufPtrs[i], request.outputBuffers[i].status,
983 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
984 &bufCache);
985 outHalBufs[i] = bufCache;
986 }
987 halRequest.output_buffers = outHalBufs.data();
Emilian Peevcf581372017-04-07 13:53:10 +0100988
989 AETriggerCancelOverride triggerOverride;
990 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
991 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
992 if (aeCancelTriggerNeeded) {
993 mInflightAETriggerOverrides[halRequest.frame_number] =
994 triggerOverride;
995 halRequest.settings = settingsOverride.getAndLock();
996 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700997 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700998
999 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
1000 ATRACE_BEGIN("camera3->process_capture_request");
1001 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
1002 ATRACE_END();
Emilian Peevcf581372017-04-07 13:53:10 +01001003 if (aeCancelTriggerNeeded) {
1004 settingsOverride.unlock(halRequest.settings);
1005 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001006 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001007 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001008 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
1009
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001010 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001011 if (hasInputBuf) {
1012 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
1013 mInflightBuffers.erase(key);
1014 }
1015 for (size_t i = 0; i < numOutputBufs; i++) {
1016 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1017 mInflightBuffers.erase(key);
1018 }
Emilian Peevcf581372017-04-07 13:53:10 +01001019 if (aeCancelTriggerNeeded) {
1020 mInflightAETriggerOverrides.erase(request.frameNumber);
1021 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001022 return Status::INTERNAL_ERROR;
1023 }
1024
1025 return Status::OK;
1026}
1027
1028Return<Status> CameraDeviceSession::flush() {
1029 Status status = initStatus();
1030 if (status == Status::OK) {
1031 // Flush is always supported on device 3.1 or later
1032 status_t ret = mDevice->ops->flush(mDevice);
1033 if (ret != OK) {
1034 status = Status::INTERNAL_ERROR;
1035 }
1036 }
1037 return status;
1038}
1039
1040Return<void> CameraDeviceSession::close() {
1041 Mutex::Autolock _l(mStateLock);
1042 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001043 {
1044 Mutex::Autolock _l(mInflightLock);
1045 if (!mInflightBuffers.empty()) {
1046 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
1047 __FUNCTION__, mInflightBuffers.size());
1048 }
Emilian Peevcf581372017-04-07 13:53:10 +01001049 if (!mInflightAETriggerOverrides.empty()) {
1050 ALOGE("%s: trying to close while there are still %zu inflight "
1051 "trigger overrides!", __FUNCTION__,
1052 mInflightAETriggerOverrides.size());
1053 }
1054
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001055 }
1056
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001057 ATRACE_BEGIN("camera3->close");
1058 mDevice->common.close(&mDevice->common);
1059 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001060
1061 // free all imported buffers
1062 for(auto& pair : mCirculatingBuffers) {
1063 CirculatingBuffers& buffers = pair.second;
1064 for (auto& p2 : buffers) {
1065 sHandleImporter.freeBuffer(p2.second);
1066 }
1067 }
1068
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001069 mClosed = true;
1070 }
1071 return Void();
1072}
1073
1074/**
1075 * Static callback forwarding methods from HAL to instance
1076 */
1077void CameraDeviceSession::sProcessCaptureResult(
1078 const camera3_callback_ops *cb,
1079 const camera3_capture_result *hal_result) {
1080 CameraDeviceSession *d =
1081 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1082
1083 uint32_t frameNumber = hal_result->frame_number;
1084 bool hasInputBuf = (hal_result->input_buffer != nullptr);
1085 size_t numOutputBufs = hal_result->num_output_buffers;
1086 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001087 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001088 Mutex::Autolock _l(d->mInflightLock);
1089 if (hasInputBuf) {
1090 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1091 // validate if buffer is inflight
1092 auto key = std::make_pair(streamId, frameNumber);
1093 if (d->mInflightBuffers.count(key) != 1) {
1094 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
1095 __FUNCTION__, streamId, frameNumber);
1096 return;
1097 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001098 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001099
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001100 for (size_t i = 0; i < numOutputBufs; i++) {
1101 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1102 // validate if buffer is inflight
1103 auto key = std::make_pair(streamId, frameNumber);
1104 if (d->mInflightBuffers.count(key) != 1) {
1105 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
1106 __FUNCTION__, streamId, frameNumber);
1107 return;
1108 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001109 }
1110 }
1111 // We don't need to validate/import fences here since we will be passing them to camera service
1112 // within the scope of this function
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001113 CaptureResult result;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001114 result.frameNumber = frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -07001115 result.fmqResultSize = 0;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001116 result.partialResult = hal_result->partial_result;
1117 convertToHidl(hal_result->result, &result.result);
Emilian Peevcf581372017-04-07 13:53:10 +01001118 if (nullptr != hal_result->result) {
1119 Mutex::Autolock _l(d->mInflightLock);
1120 auto entry = d->mInflightAETriggerOverrides.find(frameNumber);
1121 if (d->mInflightAETriggerOverrides.end() != entry) {
1122 d->mOverridenResult.clear();
1123 d->mOverridenResult.append(hal_result->result);
1124 d->overrideResultForPrecaptureCancelLocked(entry->second,
1125 &d->mOverridenResult);
1126 const camera_metadata_t *metaBuffer = d->mOverridenResult.getAndLock();
1127 convertToHidl(metaBuffer, &result.result);
1128 d->mOverridenResult.unlock(metaBuffer);
1129 if (hal_result->partial_result == d->mNumPartialResults) {
1130 d->mInflightAETriggerOverrides.erase(frameNumber);
1131 }
1132 }
1133 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001134 if (hasInputBuf) {
1135 result.inputBuffer.streamId =
1136 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1137 result.inputBuffer.buffer = nullptr;
1138 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
1139 // skip acquire fence since it's no use to camera service
1140 if (hal_result->input_buffer->release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001141 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1142 handle->data[0] = hal_result->input_buffer->release_fence;
1143 result.inputBuffer.releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001144 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001145 result.inputBuffer.releaseFence = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001146 }
1147 } else {
1148 result.inputBuffer.streamId = -1;
1149 }
1150
1151 result.outputBuffers.resize(numOutputBufs);
1152 for (size_t i = 0; i < numOutputBufs; i++) {
1153 result.outputBuffers[i].streamId =
1154 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1155 result.outputBuffers[i].buffer = nullptr;
1156 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
1157 // skip acquire fence since it's of no use to camera service
1158 if (hal_result->output_buffers[i].release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001159 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1160 handle->data[0] = hal_result->output_buffers[i].release_fence;
1161 result.outputBuffers[i].releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001162 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001163 result.outputBuffers[i].releaseFence = nullptr;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001164 }
1165 }
1166
1167 // Free inflight record/fences.
1168 // Do this before call back to camera service because camera service might jump to
1169 // configure_streams right after the processCaptureResult call so we need to finish
1170 // updating inflight queues first
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001171 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001172 Mutex::Autolock _l(d->mInflightLock);
1173 if (hasInputBuf) {
1174 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1175 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001176 d->mInflightBuffers.erase(key);
1177 }
1178
1179 for (size_t i = 0; i < numOutputBufs; i++) {
1180 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1181 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001182 d->mInflightBuffers.erase(key);
1183 }
1184
1185 if (d->mInflightBuffers.empty()) {
1186 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001187 }
1188 }
1189
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001190 d->mResultBatcher.processCaptureResult(result);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001191}
1192
1193void CameraDeviceSession::sNotify(
1194 const camera3_callback_ops *cb,
1195 const camera3_notify_msg *msg) {
1196 CameraDeviceSession *d =
1197 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1198 NotifyMsg hidlMsg;
1199 convertToHidl(msg, &hidlMsg);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001200
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001201 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
1202 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001203 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
1204 ALOGE("%s: unknown stream ID %d reports an error!",
1205 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001206 return;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001207 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001208 }
Emilian Peevcf581372017-04-07 13:53:10 +01001209
1210 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
1211 switch (hidlMsg.msg.error.errorCode) {
1212 case ErrorCode::ERROR_DEVICE:
1213 case ErrorCode::ERROR_REQUEST:
1214 case ErrorCode::ERROR_RESULT: {
1215 Mutex::Autolock _l(d->mInflightLock);
1216 auto entry = d->mInflightAETriggerOverrides.find(
1217 hidlMsg.msg.error.frameNumber);
1218 if (d->mInflightAETriggerOverrides.end() != entry) {
1219 d->mInflightAETriggerOverrides.erase(
1220 hidlMsg.msg.error.frameNumber);
1221 }
1222 }
1223 break;
1224 case ErrorCode::ERROR_BUFFER:
1225 default:
1226 break;
1227 }
1228
1229 }
1230
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001231 d->mResultBatcher.notify(hidlMsg);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001232}
1233
1234} // namespace implementation
1235} // namespace V3_2
1236} // namespace device
1237} // namespace camera
1238} // namespace hardware
1239} // namespace android