blob: b7187232f8fe21418ae763ffbe965242c9e8caff [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),
Emilian Peeva13ac992017-04-10 12:02:17 +010049 mDerivePostRawSensKey(false),
Emilian Peevcf581372017-04-07 13:53:10 +010050 mNumPartialResults(1),
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080051 mResultBatcher(callback) {
52
53 mDeviceInfo = deviceInfo;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080054 camera_metadata_entry partialResultsCount =
55 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
56 if (partialResultsCount.count > 0) {
Emilian Peevcf581372017-04-07 13:53:10 +010057 mNumPartialResults = partialResultsCount.data.i32[0];
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080058 }
Emilian Peevcf581372017-04-07 13:53:10 +010059 mResultBatcher.setNumPartialResults(mNumPartialResults);
60
61 camera_metadata_entry aeLockAvailableEntry = mDeviceInfo.find(
62 ANDROID_CONTROL_AE_LOCK_AVAILABLE);
63 if (aeLockAvailableEntry.count > 0) {
64 mIsAELockAvailable = (aeLockAvailableEntry.data.u8[0] ==
65 ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
66 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080067
Emilian Peeva13ac992017-04-10 12:02:17 +010068 // Determine whether we need to derive sensitivity boost values for older devices.
69 // If post-RAW sensitivity boost range is listed, so should post-raw sensitivity control
70 // be listed (as the default value 100)
71 if (mDeviceInfo.exists(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE)) {
72 mDerivePostRawSensKey = true;
73 }
74
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070075 mInitFail = initialize();
76}
77
78bool CameraDeviceSession::initialize() {
79 /** Initialize device with callback functions */
80 ATRACE_BEGIN("camera3->initialize");
81 status_t res = mDevice->ops->initialize(mDevice, this);
82 ATRACE_END();
83
84 if (res != OK) {
85 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
86 __FUNCTION__, strerror(-res), res);
87 mDevice->common.close(&mDevice->common);
88 mClosed = true;
89 return true;
90 }
Yifan Hong1192e1d2017-04-11 14:45:00 -070091
92 mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
93 CAMERA_REQUEST_METADATA_QUEUE_SIZE, false /* non blocking */);
94 if (!mRequestMetadataQueue->isValid()) {
Yifan Hong993e3d02017-04-12 16:31:23 -070095 ALOGE("%s: invalid request fmq", __FUNCTION__);
Yifan Hong1192e1d2017-04-11 14:45:00 -070096 return true;
97 }
Yifan Hong993e3d02017-04-12 16:31:23 -070098 mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
99 CAMERA_RESULT_METADATA_QUEUE_SIZE, false /* non blocking */);
100 if (!mResultMetadataQueue->isValid()) {
101 ALOGE("%s: invalid result fmq", __FUNCTION__);
102 return true;
103 }
104 mResultBatcher.setResultMetadataQueue(mResultMetadataQueue);
Yifan Hong1192e1d2017-04-11 14:45:00 -0700105
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700106 return false;
107}
108
109CameraDeviceSession::~CameraDeviceSession() {
110 if (!isClosed()) {
111 ALOGE("CameraDeviceSession deleted before close!");
112 close();
113 }
114}
115
116bool CameraDeviceSession::isClosed() {
117 Mutex::Autolock _l(mStateLock);
118 return mClosed;
119}
120
121Status CameraDeviceSession::initStatus() const {
122 Mutex::Autolock _l(mStateLock);
123 Status status = Status::OK;
124 if (mInitFail) {
125 status = Status::INTERNAL_ERROR;
126 } else if (mDisconnected) {
127 status = Status::CAMERA_DISCONNECTED;
128 } else if (mClosed) {
129 status = Status::INTERNAL_ERROR;
130 }
131 return status;
132}
133
134void CameraDeviceSession::disconnect() {
135 Mutex::Autolock _l(mStateLock);
136 mDisconnected = true;
137 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
138 if (!mClosed) {
139 mDevice->common.close(&mDevice->common);
140 mClosed = true;
141 }
142}
143
144void CameraDeviceSession::dumpState(const native_handle_t* fd) {
145 if (!isClosed()) {
146 mDevice->ops->dump(mDevice, fd->data[0]);
147 }
148}
149
Emilian Peevcf581372017-04-07 13:53:10 +0100150/**
151 * For devices <= CAMERA_DEVICE_API_VERSION_3_2, AE_PRECAPTURE_TRIGGER_CANCEL is not supported so
152 * we need to override AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE and AE_LOCK_OFF
153 * to AE_LOCK_ON to start cancelling AE precapture. If AE lock is not available, it still overrides
154 * AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE but doesn't add AE_LOCK_ON to the
155 * request.
156 */
157bool CameraDeviceSession::handleAePrecaptureCancelRequestLocked(
158 const camera3_capture_request_t &halRequest,
159 ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/,
160 AETriggerCancelOverride *override /*out*/) {
161 if ((mDeviceVersion > CAMERA_DEVICE_API_VERSION_3_2) ||
162 (nullptr == halRequest.settings) || (nullptr == settings) ||
163 (0 == get_camera_metadata_entry_count(halRequest.settings))) {
164 return false;
165 }
166
167 settings->clear();
168 settings->append(halRequest.settings);
169 camera_metadata_entry_t aePrecaptureTrigger =
170 settings->find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
171 if (aePrecaptureTrigger.count > 0 &&
172 aePrecaptureTrigger.data.u8[0] ==
173 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL) {
174 // Always override CANCEL to IDLE
175 uint8_t aePrecaptureTrigger =
176 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
177 settings->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
178 &aePrecaptureTrigger, 1);
179 *override = { false, ANDROID_CONTROL_AE_LOCK_OFF,
180 true, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL };
181
182 if (mIsAELockAvailable == true) {
183 camera_metadata_entry_t aeLock = settings->find(
184 ANDROID_CONTROL_AE_LOCK);
185 if (aeLock.count == 0 || aeLock.data.u8[0] ==
186 ANDROID_CONTROL_AE_LOCK_OFF) {
187 uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_ON;
188 settings->update(ANDROID_CONTROL_AE_LOCK, &aeLock, 1);
189 override->applyAeLock = true;
190 override->aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
191 }
192 }
193
194 return true;
195 }
196
197 return false;
198}
199
200/**
201 * Override result metadata for cancelling AE precapture trigger applied in
202 * handleAePrecaptureCancelRequestLocked().
203 */
204void CameraDeviceSession::overrideResultForPrecaptureCancelLocked(
205 const AETriggerCancelOverride &aeTriggerCancelOverride,
206 ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/) {
207 if (aeTriggerCancelOverride.applyAeLock) {
208 // Only devices <= v3.2 should have this override
209 assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
210 settings->update(ANDROID_CONTROL_AE_LOCK, &aeTriggerCancelOverride.aeLock, 1);
211 }
212
213 if (aeTriggerCancelOverride.applyAePrecaptureTrigger) {
214 // Only devices <= v3.2 should have this override
215 assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
216 settings->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
217 &aeTriggerCancelOverride.aePrecaptureTrigger, 1);
218 }
219}
220
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700221Status CameraDeviceSession::importRequest(
222 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800223 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700224 hidl_vec<int>& allFences) {
225 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800226 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700227 size_t numOutputBufs = request.outputBuffers.size();
228 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
229 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800230 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800231 hidl_vec<uint64_t> allBufIds;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700232 allBufs.resize(numBufs);
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800233 allBufIds.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800234 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700235 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800236 std::vector<int32_t> streamIds(numBufs);
237
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700238 for (size_t i = 0; i < numOutputBufs; i++) {
239 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800240 allBufIds[i] = request.outputBuffers[i].bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800241 allBufPtrs[i] = &allBufs[i];
242 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700243 }
244 if (hasInputBuf) {
245 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800246 allBufIds[numOutputBufs] = request.inputBuffer.bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800247 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
248 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700249 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800250
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700251 for (size_t i = 0; i < numBufs; i++) {
252 buffer_handle_t buf = allBufs[i];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800253 uint64_t bufId = allBufIds[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800254 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800255 if (cbs.count(bufId) == 0) {
256 if (buf == nullptr) {
257 ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
258 return Status::ILLEGAL_ARGUMENT;
259 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800260 // Register a newly seen buffer
261 buffer_handle_t importedBuf = buf;
262 sHandleImporter.importBuffer(importedBuf);
263 if (importedBuf == nullptr) {
264 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
265 return Status::INTERNAL_ERROR;
266 } else {
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800267 cbs[bufId] = importedBuf;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800268 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700269 }
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800270 allBufPtrs[i] = &cbs[bufId];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700271 }
272
273 // All buffers are imported. Now validate output buffer acquire fences
274 for (size_t i = 0; i < numOutputBufs; i++) {
275 if (!sHandleImporter.importFence(
276 request.outputBuffers[i].acquireFence, allFences[i])) {
277 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800278 cleanupInflightFences(allFences, i);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700279 return Status::INTERNAL_ERROR;
280 }
281 }
282
283 // Validate input buffer acquire fences
284 if (hasInputBuf) {
285 if (!sHandleImporter.importFence(
286 request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
287 ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800288 cleanupInflightFences(allFences, numOutputBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700289 return Status::INTERNAL_ERROR;
290 }
291 }
292 return Status::OK;
293}
294
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800295void CameraDeviceSession::cleanupInflightFences(
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700296 hidl_vec<int>& allFences, size_t numFences) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700297 for (size_t j = 0; j < numFences; j++) {
298 sHandleImporter.closeFence(allFences[j]);
299 }
300}
301
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800302CameraDeviceSession::ResultBatcher::ResultBatcher(
303 const sp<ICameraDeviceCallback>& callback) : mCallback(callback) {};
304
305bool CameraDeviceSession::ResultBatcher::InflightBatch::allDelivered() const {
306 if (!mShutterDelivered) return false;
307
308 if (mPartialResultProgress < mNumPartialResults) {
309 return false;
310 }
311
312 for (const auto& pair : mBatchBufs) {
313 if (!pair.second.mDelivered) {
314 return false;
315 }
316 }
317 return true;
318}
319
320void CameraDeviceSession::ResultBatcher::setNumPartialResults(uint32_t n) {
321 Mutex::Autolock _l(mLock);
322 mNumPartialResults = n;
323}
324
325void CameraDeviceSession::ResultBatcher::setBatchedStreams(
326 const std::vector<int>& streamsToBatch) {
327 Mutex::Autolock _l(mLock);
328 mStreamsToBatch = streamsToBatch;
329}
330
Yifan Hong993e3d02017-04-12 16:31:23 -0700331void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(std::shared_ptr<ResultMetadataQueue> q) {
332 Mutex::Autolock _l(mLock);
333 mResultMetadataQueue = q;
334}
335
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800336void CameraDeviceSession::ResultBatcher::registerBatch(
337 const hidl_vec<CaptureRequest>& requests) {
338 auto batch = std::make_shared<InflightBatch>();
339 batch->mFirstFrame = requests[0].frameNumber;
340 batch->mBatchSize = requests.size();
341 batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
342 batch->mNumPartialResults = mNumPartialResults;
343 for (int id : mStreamsToBatch) {
344 batch->mBatchBufs[id] = InflightBatch::BufferBatch();
345 }
346 Mutex::Autolock _l(mLock);
347 mInflightBatches.push_back(batch);
348}
349
350std::pair<int, std::shared_ptr<CameraDeviceSession::ResultBatcher::InflightBatch>>
351CameraDeviceSession::ResultBatcher::getBatch(
352 uint32_t frameNumber) {
353 Mutex::Autolock _l(mLock);
354 int numBatches = mInflightBatches.size();
355 if (numBatches == 0) {
356 return std::make_pair(NOT_BATCHED, nullptr);
357 }
358 uint32_t frameMin = mInflightBatches[0]->mFirstFrame;
359 uint32_t frameMax = mInflightBatches[numBatches - 1]->mLastFrame;
360 if (frameNumber < frameMin || frameNumber > frameMax) {
361 return std::make_pair(NOT_BATCHED, nullptr);
362 }
363 for (int i = 0; i < numBatches; i++) {
364 if (frameNumber >= mInflightBatches[i]->mFirstFrame &&
365 frameNumber <= mInflightBatches[i]->mLastFrame) {
366 return std::make_pair(i, mInflightBatches[i]);
367 }
368 }
369 return std::make_pair(NOT_BATCHED, nullptr);
370}
371
372void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
373 Mutex::Autolock _l(mLock);
374 if (mInflightBatches.size() > 0) {
375 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
376 bool shouldRemove = false;
377 {
378 Mutex::Autolock _l(batch->mLock);
379 if (batch->allDelivered()) {
380 batch->mRemoved = true;
381 shouldRemove = true;
382 }
383 }
384 if (shouldRemove) {
385 mInflightBatches.pop_front();
386 }
387 }
388}
389
390void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch) {
391 if (batch->mShutterDelivered) {
392 ALOGW("%s: batch shutter callback already sent!", __FUNCTION__);
393 return;
394 }
395
396 mCallback->notify(batch->mShutterMsgs);
397 batch->mShutterDelivered = true;
398 batch->mShutterMsgs.clear();
399}
400
401void CameraDeviceSession::ResultBatcher::freeReleaseFences(hidl_vec<CaptureResult>& results) {
402 for (auto& result : results) {
403 if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
404 native_handle_t* handle = const_cast<native_handle_t*>(
405 result.inputBuffer.releaseFence.getNativeHandle());
406 native_handle_delete(handle);
407 }
408 for (auto& buf : result.outputBuffers) {
409 if (buf.releaseFence.getNativeHandle() != nullptr) {
410 native_handle_t* handle = const_cast<native_handle_t*>(
411 buf.releaseFence.getNativeHandle());
412 native_handle_delete(handle);
413 }
414 }
415 }
416 return;
417}
418
419void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
420 sendBatchBuffersLocked(batch, mStreamsToBatch);
421}
422
423void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
424 std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
425 size_t batchSize = 0;
426 for (int streamId : streams) {
427 auto it = batch->mBatchBufs.find(streamId);
428 if (it != batch->mBatchBufs.end()) {
429 InflightBatch::BufferBatch& bb = it->second;
430 if (bb.mDelivered) {
431 continue;
432 }
433 if (bb.mBuffers.size() > batchSize) {
434 batchSize = bb.mBuffers.size();
435 }
436 } else {
437 ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
438 return;
439 }
440 }
441
442 if (batchSize == 0) {
443 ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
444 for (int streamId : streams) {
445 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
446 bb.mDelivered = true;
447 }
448 return;
449 }
450
451 hidl_vec<CaptureResult> results;
452 results.resize(batchSize);
453 for (size_t i = 0; i < batchSize; i++) {
454 results[i].frameNumber = batch->mFirstFrame + i;
Yifan Hong993e3d02017-04-12 16:31:23 -0700455 results[i].fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800456 results[i].partialResult = 0; // 0 for buffer only results
457 results[i].inputBuffer.streamId = -1;
458 results[i].inputBuffer.bufferId = 0;
459 results[i].inputBuffer.buffer = nullptr;
460 std::vector<StreamBuffer> outBufs;
461 for (int streamId : streams) {
462 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
463 if (bb.mDelivered) {
464 continue;
465 }
466 if (i < bb.mBuffers.size()) {
467 outBufs.push_back(bb.mBuffers[i]);
468 }
469 }
470 results[i].outputBuffers = outBufs;
471 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700472 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */false);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800473 freeReleaseFences(results);
474 for (int streamId : streams) {
475 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
476 bb.mDelivered = true;
477 bb.mBuffers.clear();
478 }
479}
480
481void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
482 std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
483 if (lastPartialResultIdx <= batch->mPartialResultProgress) {
484 // Result has been delivered. Return
485 ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
486 return;
487 }
488
489 std::vector<CaptureResult> results;
490 std::vector<uint32_t> toBeRemovedIdxes;
491 for (auto& pair : batch->mResultMds) {
492 uint32_t partialIdx = pair.first;
493 if (partialIdx > lastPartialResultIdx) {
494 continue;
495 }
496 toBeRemovedIdxes.push_back(partialIdx);
497 InflightBatch::MetadataBatch& mb = pair.second;
498 for (const auto& p : mb.mMds) {
499 CaptureResult result;
500 result.frameNumber = p.first;
501 result.result = std::move(p.second);
Yifan Hong993e3d02017-04-12 16:31:23 -0700502 result.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800503 result.inputBuffer.streamId = -1;
504 result.inputBuffer.bufferId = 0;
505 result.inputBuffer.buffer = nullptr;
506 result.partialResult = partialIdx;
507 results.push_back(std::move(result));
508 }
509 mb.mMds.clear();
510 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700511 hidl_vec<CaptureResult> hResults;
512 hResults.setToExternal(results.data(), results.size());
513 invokeProcessCaptureResultCallback(hResults, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800514 batch->mPartialResultProgress = lastPartialResultIdx;
515 for (uint32_t partialIdx : toBeRemovedIdxes) {
516 batch->mResultMds.erase(partialIdx);
517 }
518}
519
520void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
521 mCallback->notify({msg});
522 return;
523}
524
525void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
526 uint32_t frameNumber;
527 if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
528 frameNumber = msg.msg.shutter.frameNumber;
529 } else {
530 frameNumber = msg.msg.error.frameNumber;
531 }
532
533 auto pair = getBatch(frameNumber);
534 int batchIdx = pair.first;
535 if (batchIdx == NOT_BATCHED) {
536 notifySingleMsg(msg);
537 return;
538 }
539
540 // When error happened, stop batching for all batches earlier
541 if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
542 Mutex::Autolock _l(mLock);
543 for (int i = 0; i <= batchIdx; i++) {
544 // Send batched data up
545 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
546 {
547 Mutex::Autolock _l(batch->mLock);
548 sendBatchShutterCbsLocked(batch);
549 sendBatchBuffersLocked(batch);
550 sendBatchMetadataLocked(batch, mNumPartialResults);
551 if (!batch->allDelivered()) {
552 ALOGE("%s: error: some batch data not sent back to framework!",
553 __FUNCTION__);
554 }
555 batch->mRemoved = true;
556 }
557 mInflightBatches.pop_front();
558 }
559 // Send the error up
560 notifySingleMsg(msg);
561 return;
562 }
563 // Queue shutter callbacks for future delivery
564 std::shared_ptr<InflightBatch> batch = pair.second;
565 {
566 Mutex::Autolock _l(batch->mLock);
567 // Check if the batch is removed (mostly by notify error) before lock was acquired
568 if (batch->mRemoved) {
569 // Fall back to non-batch path
570 notifySingleMsg(msg);
571 return;
572 }
573
574 batch->mShutterMsgs.push_back(msg);
575 if (frameNumber == batch->mLastFrame) {
576 sendBatchShutterCbsLocked(batch);
577 }
578 } // end of batch lock scope
579
580 // see if the batch is complete
581 if (frameNumber == batch->mLastFrame) {
582 checkAndRemoveFirstBatch();
583 }
584}
585
Yifan Hong993e3d02017-04-12 16:31:23 -0700586void CameraDeviceSession::ResultBatcher::invokeProcessCaptureResultCallback(
587 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
588 if (mProcessCaptureResultLock.tryLock() != OK) {
589 ALOGW("%s: previous call is not finished! waiting 1s...",
590 __FUNCTION__);
591 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
592 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
593 __FUNCTION__);
594 return;
595 }
596 }
597 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
598 for (CaptureResult &result : results) {
599 if (result.result.size() > 0) {
600 if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
601 result.fmqResultSize = result.result.size();
602 result.result.resize(0);
603 } else {
604 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
605 result.fmqResultSize = 0;
606 }
607 }
608 }
609 }
610 mCallback->processCaptureResult(results);
611 mProcessCaptureResultLock.unlock();
612}
613
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800614void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
615 hidl_vec<CaptureResult> results = {result};
Yifan Hong993e3d02017-04-12 16:31:23 -0700616 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800617 freeReleaseFences(results);
618 return;
619}
620
621void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
622 auto pair = getBatch(result.frameNumber);
623 int batchIdx = pair.first;
624 if (batchIdx == NOT_BATCHED) {
625 processOneCaptureResult(result);
626 return;
627 }
628 std::shared_ptr<InflightBatch> batch = pair.second;
629 {
630 Mutex::Autolock _l(batch->mLock);
631 // Check if the batch is removed (mostly by notify error) before lock was acquired
632 if (batch->mRemoved) {
633 // Fall back to non-batch path
634 processOneCaptureResult(result);
635 return;
636 }
637
638 // queue metadata
639 if (result.result.size() != 0) {
640 // Save a copy of metadata
641 batch->mResultMds[result.partialResult].mMds.push_back(
642 std::make_pair(result.frameNumber, result.result));
643 }
644
645 // queue buffer
646 std::vector<int> filledStreams;
647 std::vector<StreamBuffer> nonBatchedBuffers;
648 for (auto& buffer : result.outputBuffers) {
649 auto it = batch->mBatchBufs.find(buffer.streamId);
650 if (it != batch->mBatchBufs.end()) {
651 InflightBatch::BufferBatch& bb = it->second;
652 bb.mBuffers.push_back(buffer);
653 filledStreams.push_back(buffer.streamId);
654 } else {
655 nonBatchedBuffers.push_back(buffer);
656 }
657 }
658
659 // send non-batched buffers up
660 if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
661 CaptureResult nonBatchedResult;
662 nonBatchedResult.frameNumber = result.frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -0700663 nonBatchedResult.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800664 nonBatchedResult.outputBuffers = nonBatchedBuffers;
665 nonBatchedResult.inputBuffer = result.inputBuffer;
666 nonBatchedResult.partialResult = 0; // 0 for buffer only results
667 processOneCaptureResult(nonBatchedResult);
668 }
669
670 if (result.frameNumber == batch->mLastFrame) {
671 // Send data up
672 if (result.partialResult > 0) {
673 sendBatchMetadataLocked(batch, result.partialResult);
674 }
675 // send buffer up
676 if (filledStreams.size() > 0) {
677 sendBatchBuffersLocked(batch, filledStreams);
678 }
679 }
680 } // end of batch lock scope
681
682 // see if the batch is complete
683 if (result.frameNumber == batch->mLastFrame) {
684 checkAndRemoveFirstBatch();
685 }
686}
687
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700688// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
689Return<void> CameraDeviceSession::constructDefaultRequestSettings(
690 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
691 Status status = initStatus();
692 CameraMetadata outMetadata;
693 const camera_metadata_t *rawRequest;
694 if (status == Status::OK) {
695 ATRACE_BEGIN("camera3->construct_default_request_settings");
696 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
697 ATRACE_END();
698 if (rawRequest == nullptr) {
699 ALOGI("%s: template %d is not supported on this camera device",
700 __FUNCTION__, type);
701 status = Status::ILLEGAL_ARGUMENT;
702 } else {
Emilian Peeva13ac992017-04-10 12:02:17 +0100703 mOverridenRequest.clear();
704 mOverridenRequest.append(rawRequest);
705 // Derive some new keys for backward compatibility
706 if (mDerivePostRawSensKey && !mOverridenRequest.exists(
707 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST)) {
708 int32_t defaultBoost[1] = {100};
709 mOverridenRequest.update(
710 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
711 defaultBoost, 1);
712 const camera_metadata_t *metaBuffer =
713 mOverridenRequest.getAndLock();
714 convertToHidl(metaBuffer, &outMetadata);
715 mOverridenRequest.unlock(metaBuffer);
716 } else {
717 convertToHidl(rawRequest, &outMetadata);
718 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700719 }
720 }
721 _hidl_cb(status, outMetadata);
722 return Void();
723}
724
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100725/**
726 * Map Android N dataspace definitions back to Android M definitions, for
727 * use with HALv3.3 or older.
728 *
729 * Only map where correspondences exist, and otherwise preserve the value.
730 */
731android_dataspace CameraDeviceSession::mapToLegacyDataspace(
732 android_dataspace dataSpace) const {
733 if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
734 switch (dataSpace) {
735 case HAL_DATASPACE_V0_SRGB_LINEAR:
736 return HAL_DATASPACE_SRGB_LINEAR;
737 case HAL_DATASPACE_V0_SRGB:
738 return HAL_DATASPACE_SRGB;
739 case HAL_DATASPACE_V0_JFIF:
740 return HAL_DATASPACE_JFIF;
741 case HAL_DATASPACE_V0_BT601_625:
742 return HAL_DATASPACE_BT601_625;
743 case HAL_DATASPACE_V0_BT601_525:
744 return HAL_DATASPACE_BT601_525;
745 case HAL_DATASPACE_V0_BT709:
746 return HAL_DATASPACE_BT709;
747 default:
748 return dataSpace;
749 }
750 }
751
752 return dataSpace;
753}
754
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700755Return<void> CameraDeviceSession::configureStreams(
756 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
757 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800758 HalStreamConfiguration outStreams;
759
760 // hold the inflight lock for entire configureStreams scope since there must not be any
761 // inflight request/results during stream configuration.
762 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700763 if (!mInflightBuffers.empty()) {
764 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
765 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800766 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
767 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700768 }
769
Emilian Peevcf581372017-04-07 13:53:10 +0100770 if (!mInflightAETriggerOverrides.empty()) {
771 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
772 " trigger overrides!", __FUNCTION__,
773 mInflightAETriggerOverrides.size());
774 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
775 return Void();
776 }
777
Emilian Peeva13ac992017-04-10 12:02:17 +0100778 if (!mInflightRawBoostPresent.empty()) {
779 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
780 " boost overrides!", __FUNCTION__,
781 mInflightRawBoostPresent.size());
782 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
783 return Void();
784 }
785
Emilian Peev98014ff2017-02-02 16:20:12 +0000786 if (status != Status::OK) {
787 _hidl_cb(status, outStreams);
788 return Void();
789 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800790
Emilian Peev98014ff2017-02-02 16:20:12 +0000791 camera3_stream_configuration_t stream_list;
792 hidl_vec<camera3_stream_t*> streams;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800793
Emilian Peev98014ff2017-02-02 16:20:12 +0000794 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
795 stream_list.num_streams = requestedConfiguration.streams.size();
796 streams.resize(stream_list.num_streams);
797 stream_list.streams = streams.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700798
Emilian Peev98014ff2017-02-02 16:20:12 +0000799 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
800 int id = requestedConfiguration.streams[i].id;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700801
Emilian Peev98014ff2017-02-02 16:20:12 +0000802 if (mStreamMap.count(id) == 0) {
803 Camera3Stream stream;
804 convertFromHidl(requestedConfiguration.streams[i], &stream);
805 mStreamMap[id] = stream;
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100806 mStreamMap[id].data_space = mapToLegacyDataspace(
807 mStreamMap[id].data_space);
Emilian Peev98014ff2017-02-02 16:20:12 +0000808 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
809 } else {
810 // width/height/format must not change, but usage/rotation might need to change
811 if (mStreamMap[id].stream_type !=
812 (int) requestedConfiguration.streams[i].streamType ||
813 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
814 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
815 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100816 mStreamMap[id].data_space !=
817 mapToLegacyDataspace( static_cast<android_dataspace_t> (
818 requestedConfiguration.streams[i].dataSpace))) {
Emilian Peev98014ff2017-02-02 16:20:12 +0000819 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
820 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
821 return Void();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800822 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000823 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
Yin-Chia Yehc25c54f2017-04-04 13:00:35 -0700824 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700825 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000826 streams[i] = &mStreamMap[id];
827 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700828
Emilian Peev98014ff2017-02-02 16:20:12 +0000829 ATRACE_BEGIN("camera3->configure_streams");
830 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
831 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700832
Emilian Peev98014ff2017-02-02 16:20:12 +0000833 // In case Hal returns error most likely it was not able to release
834 // the corresponding resources of the deleted streams.
835 if (ret == OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800836 // delete unused streams, note we do this after adding new streams to ensure new stream
837 // will not have the same address as deleted stream, and HAL has a chance to reference
838 // the to be deleted stream in configure_streams call
839 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
840 int id = it->first;
841 bool found = false;
842 for (const auto& stream : requestedConfiguration.streams) {
843 if (id == stream.id) {
844 found = true;
845 break;
846 }
847 }
848 if (!found) {
849 // Unmap all buffers of deleted stream
Emilian Peev98014ff2017-02-02 16:20:12 +0000850 // in case the configuration call succeeds and HAL
851 // is able to release the corresponding resources too.
852 cleanupBuffersLocked(id);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800853 it = mStreamMap.erase(it);
854 } else {
855 ++it;
856 }
857 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800858
859 // Track video streams
860 mVideoStreamIds.clear();
861 for (const auto& stream : requestedConfiguration.streams) {
862 if (stream.streamType == StreamType::OUTPUT &&
Chia-I Wu79d13ff2017-03-31 12:48:11 -0700863 stream.usage &
864 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800865 mVideoStreamIds.push_back(stream.id);
866 }
867 }
868 mResultBatcher.setBatchedStreams(mVideoStreamIds);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700869 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000870
871 if (ret == -EINVAL) {
872 status = Status::ILLEGAL_ARGUMENT;
873 } else if (ret != OK) {
874 status = Status::INTERNAL_ERROR;
875 } else {
876 convertToHidl(stream_list, &outStreams);
877 }
878
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700879 _hidl_cb(status, outStreams);
880 return Void();
881}
882
Emilian Peev98014ff2017-02-02 16:20:12 +0000883// Needs to get called after acquiring 'mInflightLock'
884void CameraDeviceSession::cleanupBuffersLocked(int id) {
885 for (auto& pair : mCirculatingBuffers.at(id)) {
886 sHandleImporter.freeBuffer(pair.second);
887 }
888 mCirculatingBuffers[id].clear();
889 mCirculatingBuffers.erase(id);
890}
891
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700892void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
893 Mutex::Autolock _l(mInflightLock);
894 for (auto& cache : cachesToRemove) {
895 auto cbsIt = mCirculatingBuffers.find(cache.streamId);
896 if (cbsIt == mCirculatingBuffers.end()) {
897 // The stream could have been removed
898 continue;
899 }
900 CirculatingBuffers& cbs = cbsIt->second;
901 auto it = cbs.find(cache.bufferId);
902 if (it != cbs.end()) {
903 sHandleImporter.freeBuffer(it->second);
904 cbs.erase(it);
905 } else {
906 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
907 __FUNCTION__, cache.streamId, cache.bufferId);
908 }
909 }
910}
911
Yifan Hong1192e1d2017-04-11 14:45:00 -0700912Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
913 getCaptureRequestMetadataQueue_cb _hidl_cb) {
914 _hidl_cb(*mRequestMetadataQueue->getDesc());
915 return Void();
916}
917
Yifan Hong993e3d02017-04-12 16:31:23 -0700918Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
919 getCaptureResultMetadataQueue_cb _hidl_cb) {
920 _hidl_cb(*mResultMetadataQueue->getDesc());
921 return Void();
922}
923
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800924Return<void> CameraDeviceSession::processCaptureRequest(
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700925 const hidl_vec<CaptureRequest>& requests,
926 const hidl_vec<BufferCache>& cachesToRemove,
927 processCaptureRequest_cb _hidl_cb) {
928 updateBufferCaches(cachesToRemove);
929
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800930 uint32_t numRequestProcessed = 0;
931 Status s = Status::OK;
932 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
933 s = processOneCaptureRequest(requests[i]);
934 if (s != Status::OK) {
935 break;
936 }
937 }
938
939 if (s == Status::OK && requests.size() > 1) {
940 mResultBatcher.registerBatch(requests);
941 }
942
943 _hidl_cb(s, numRequestProcessed);
944 return Void();
945}
946
947Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700948 Status status = initStatus();
949 if (status != Status::OK) {
950 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
951 return status;
952 }
953
954 camera3_capture_request_t halRequest;
955 halRequest.frame_number = request.frameNumber;
Yifan Hong1192e1d2017-04-11 14:45:00 -0700956
957 bool converted = true;
958 CameraMetadata settingsFmq; // settings from FMQ
959 if (request.fmqSettingsSize > 0) {
960 // non-blocking read; client must write metadata before calling
961 // processOneCaptureRequest
962 settingsFmq.resize(request.fmqSettingsSize);
963 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
964 if (read) {
965 converted = convertFromHidl(settingsFmq, &halRequest.settings);
966 } else {
967 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
968 converted = false;
969 }
970 } else {
971 converted = convertFromHidl(request.settings, &halRequest.settings);
972 }
973
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700974 if (!converted) {
975 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
976 return Status::INTERNAL_ERROR;
977 }
978
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800979 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700980 hidl_vec<int> allFences;
981 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800982 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700983 size_t numOutputBufs = request.outputBuffers.size();
984 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800985 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700986 if (status != Status::OK) {
987 return status;
988 }
989
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700990 hidl_vec<camera3_stream_buffer_t> outHalBufs;
991 outHalBufs.resize(numOutputBufs);
Emilian Peevcf581372017-04-07 13:53:10 +0100992 bool aeCancelTriggerNeeded = false;
993 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800994 {
995 Mutex::Autolock _l(mInflightLock);
996 if (hasInputBuf) {
997 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
998 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
999 convertFromHidl(
1000 allBufPtrs[numOutputBufs], request.inputBuffer.status,
1001 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
1002 &bufCache);
1003 halRequest.input_buffer = &bufCache;
1004 } else {
1005 halRequest.input_buffer = nullptr;
1006 }
1007
1008 halRequest.num_output_buffers = numOutputBufs;
1009 for (size_t i = 0; i < numOutputBufs; i++) {
1010 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1011 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
1012 convertFromHidl(
1013 allBufPtrs[i], request.outputBuffers[i].status,
1014 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
1015 &bufCache);
1016 outHalBufs[i] = bufCache;
1017 }
1018 halRequest.output_buffers = outHalBufs.data();
Emilian Peevcf581372017-04-07 13:53:10 +01001019
1020 AETriggerCancelOverride triggerOverride;
1021 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
1022 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
1023 if (aeCancelTriggerNeeded) {
1024 mInflightAETriggerOverrides[halRequest.frame_number] =
1025 triggerOverride;
1026 halRequest.settings = settingsOverride.getAndLock();
1027 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001028 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001029
1030 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
1031 ATRACE_BEGIN("camera3->process_capture_request");
1032 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
1033 ATRACE_END();
Emilian Peevcf581372017-04-07 13:53:10 +01001034 if (aeCancelTriggerNeeded) {
1035 settingsOverride.unlock(halRequest.settings);
1036 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001037 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001038 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001039 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
1040
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001041 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001042 if (hasInputBuf) {
1043 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
1044 mInflightBuffers.erase(key);
1045 }
1046 for (size_t i = 0; i < numOutputBufs; i++) {
1047 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1048 mInflightBuffers.erase(key);
1049 }
Emilian Peevcf581372017-04-07 13:53:10 +01001050 if (aeCancelTriggerNeeded) {
1051 mInflightAETriggerOverrides.erase(request.frameNumber);
1052 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001053 return Status::INTERNAL_ERROR;
1054 }
1055
1056 return Status::OK;
1057}
1058
1059Return<Status> CameraDeviceSession::flush() {
1060 Status status = initStatus();
1061 if (status == Status::OK) {
1062 // Flush is always supported on device 3.1 or later
1063 status_t ret = mDevice->ops->flush(mDevice);
1064 if (ret != OK) {
1065 status = Status::INTERNAL_ERROR;
1066 }
1067 }
1068 return status;
1069}
1070
1071Return<void> CameraDeviceSession::close() {
1072 Mutex::Autolock _l(mStateLock);
1073 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001074 {
1075 Mutex::Autolock _l(mInflightLock);
1076 if (!mInflightBuffers.empty()) {
1077 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
1078 __FUNCTION__, mInflightBuffers.size());
1079 }
Emilian Peevcf581372017-04-07 13:53:10 +01001080 if (!mInflightAETriggerOverrides.empty()) {
1081 ALOGE("%s: trying to close while there are still %zu inflight "
1082 "trigger overrides!", __FUNCTION__,
1083 mInflightAETriggerOverrides.size());
1084 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001085 if (!mInflightRawBoostPresent.empty()) {
1086 ALOGE("%s: trying to close while there are still %zu inflight "
1087 " RAW boost overrides!", __FUNCTION__,
1088 mInflightRawBoostPresent.size());
1089 }
Emilian Peevcf581372017-04-07 13:53:10 +01001090
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001091 }
1092
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001093 ATRACE_BEGIN("camera3->close");
1094 mDevice->common.close(&mDevice->common);
1095 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001096
1097 // free all imported buffers
1098 for(auto& pair : mCirculatingBuffers) {
1099 CirculatingBuffers& buffers = pair.second;
1100 for (auto& p2 : buffers) {
1101 sHandleImporter.freeBuffer(p2.second);
1102 }
1103 }
1104
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001105 mClosed = true;
1106 }
1107 return Void();
1108}
1109
1110/**
1111 * Static callback forwarding methods from HAL to instance
1112 */
1113void CameraDeviceSession::sProcessCaptureResult(
1114 const camera3_callback_ops *cb,
1115 const camera3_capture_result *hal_result) {
1116 CameraDeviceSession *d =
1117 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1118
1119 uint32_t frameNumber = hal_result->frame_number;
1120 bool hasInputBuf = (hal_result->input_buffer != nullptr);
1121 size_t numOutputBufs = hal_result->num_output_buffers;
1122 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001123 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001124 Mutex::Autolock _l(d->mInflightLock);
1125 if (hasInputBuf) {
1126 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1127 // validate if buffer is inflight
1128 auto key = std::make_pair(streamId, frameNumber);
1129 if (d->mInflightBuffers.count(key) != 1) {
1130 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
1131 __FUNCTION__, streamId, frameNumber);
1132 return;
1133 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001134 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001135
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001136 for (size_t i = 0; i < numOutputBufs; i++) {
1137 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1138 // validate if buffer is inflight
1139 auto key = std::make_pair(streamId, frameNumber);
1140 if (d->mInflightBuffers.count(key) != 1) {
1141 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
1142 __FUNCTION__, streamId, frameNumber);
1143 return;
1144 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001145 }
1146 }
1147 // We don't need to validate/import fences here since we will be passing them to camera service
1148 // within the scope of this function
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001149 CaptureResult result;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001150 result.frameNumber = frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -07001151 result.fmqResultSize = 0;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001152 result.partialResult = hal_result->partial_result;
1153 convertToHidl(hal_result->result, &result.result);
Emilian Peevcf581372017-04-07 13:53:10 +01001154 if (nullptr != hal_result->result) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001155 bool resultOverriden = false;
Emilian Peevcf581372017-04-07 13:53:10 +01001156 Mutex::Autolock _l(d->mInflightLock);
Emilian Peeva13ac992017-04-10 12:02:17 +01001157
1158 // Derive some new keys for backward compatibility
1159 if (d->mDerivePostRawSensKey) {
1160 camera_metadata_ro_entry entry;
1161 if (find_camera_metadata_ro_entry(hal_result->result,
1162 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, &entry) == 0) {
1163 d->mInflightRawBoostPresent[frameNumber] = true;
1164 } else {
1165 auto entry = d->mInflightRawBoostPresent.find(frameNumber);
1166 if (d->mInflightRawBoostPresent.end() == entry) {
1167 d->mInflightRawBoostPresent[frameNumber] = false;
1168 }
1169 }
1170
1171 if ((hal_result->partial_result == d->mNumPartialResults)) {
1172 if (!d->mInflightRawBoostPresent[frameNumber]) {
1173 if (!resultOverriden) {
1174 d->mOverridenResult.clear();
1175 d->mOverridenResult.append(hal_result->result);
1176 resultOverriden = true;
1177 }
1178 int32_t defaultBoost[1] = {100};
1179 d->mOverridenResult.update(
1180 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
1181 defaultBoost, 1);
1182 }
1183
1184 d->mInflightRawBoostPresent.erase(frameNumber);
1185 }
1186 }
1187
Emilian Peevcf581372017-04-07 13:53:10 +01001188 auto entry = d->mInflightAETriggerOverrides.find(frameNumber);
1189 if (d->mInflightAETriggerOverrides.end() != entry) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001190 if (!resultOverriden) {
1191 d->mOverridenResult.clear();
1192 d->mOverridenResult.append(hal_result->result);
1193 resultOverriden = true;
1194 }
Emilian Peevcf581372017-04-07 13:53:10 +01001195 d->overrideResultForPrecaptureCancelLocked(entry->second,
1196 &d->mOverridenResult);
Emilian Peevcf581372017-04-07 13:53:10 +01001197 if (hal_result->partial_result == d->mNumPartialResults) {
1198 d->mInflightAETriggerOverrides.erase(frameNumber);
1199 }
1200 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001201
1202 if (resultOverriden) {
1203 const camera_metadata_t *metaBuffer =
1204 d->mOverridenResult.getAndLock();
1205 convertToHidl(metaBuffer, &result.result);
1206 d->mOverridenResult.unlock(metaBuffer);
1207 }
Emilian Peevcf581372017-04-07 13:53:10 +01001208 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001209 if (hasInputBuf) {
1210 result.inputBuffer.streamId =
1211 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1212 result.inputBuffer.buffer = nullptr;
1213 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
1214 // skip acquire fence since it's no use to camera service
1215 if (hal_result->input_buffer->release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001216 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1217 handle->data[0] = hal_result->input_buffer->release_fence;
1218 result.inputBuffer.releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001219 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001220 result.inputBuffer.releaseFence = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001221 }
1222 } else {
1223 result.inputBuffer.streamId = -1;
1224 }
1225
1226 result.outputBuffers.resize(numOutputBufs);
1227 for (size_t i = 0; i < numOutputBufs; i++) {
1228 result.outputBuffers[i].streamId =
1229 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1230 result.outputBuffers[i].buffer = nullptr;
1231 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
1232 // skip acquire fence since it's of no use to camera service
1233 if (hal_result->output_buffers[i].release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001234 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1235 handle->data[0] = hal_result->output_buffers[i].release_fence;
1236 result.outputBuffers[i].releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001237 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001238 result.outputBuffers[i].releaseFence = nullptr;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001239 }
1240 }
1241
1242 // Free inflight record/fences.
1243 // Do this before call back to camera service because camera service might jump to
1244 // configure_streams right after the processCaptureResult call so we need to finish
1245 // updating inflight queues first
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001246 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001247 Mutex::Autolock _l(d->mInflightLock);
1248 if (hasInputBuf) {
1249 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1250 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001251 d->mInflightBuffers.erase(key);
1252 }
1253
1254 for (size_t i = 0; i < numOutputBufs; i++) {
1255 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1256 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001257 d->mInflightBuffers.erase(key);
1258 }
1259
1260 if (d->mInflightBuffers.empty()) {
1261 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001262 }
1263 }
1264
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001265 d->mResultBatcher.processCaptureResult(result);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001266}
1267
1268void CameraDeviceSession::sNotify(
1269 const camera3_callback_ops *cb,
1270 const camera3_notify_msg *msg) {
1271 CameraDeviceSession *d =
1272 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1273 NotifyMsg hidlMsg;
1274 convertToHidl(msg, &hidlMsg);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001275
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001276 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
1277 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001278 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
1279 ALOGE("%s: unknown stream ID %d reports an error!",
1280 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001281 return;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001282 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001283 }
Emilian Peevcf581372017-04-07 13:53:10 +01001284
1285 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
1286 switch (hidlMsg.msg.error.errorCode) {
1287 case ErrorCode::ERROR_DEVICE:
1288 case ErrorCode::ERROR_REQUEST:
1289 case ErrorCode::ERROR_RESULT: {
1290 Mutex::Autolock _l(d->mInflightLock);
1291 auto entry = d->mInflightAETriggerOverrides.find(
1292 hidlMsg.msg.error.frameNumber);
1293 if (d->mInflightAETriggerOverrides.end() != entry) {
1294 d->mInflightAETriggerOverrides.erase(
1295 hidlMsg.msg.error.frameNumber);
1296 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001297
1298 auto boostEntry = d->mInflightRawBoostPresent.find(
1299 hidlMsg.msg.error.frameNumber);
1300 if (d->mInflightRawBoostPresent.end() != boostEntry) {
1301 d->mInflightRawBoostPresent.erase(
1302 hidlMsg.msg.error.frameNumber);
1303 }
1304
Emilian Peevcf581372017-04-07 13:53:10 +01001305 }
1306 break;
1307 case ErrorCode::ERROR_BUFFER:
1308 default:
1309 break;
1310 }
1311
1312 }
1313
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001314 d->mResultBatcher.notify(hidlMsg);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001315}
1316
1317} // namespace implementation
1318} // namespace V3_2
1319} // namespace device
1320} // namespace camera
1321} // namespace hardware
1322} // namespace android