blob: 06a6bd01d6c321d1a5a5dc91d658d251a6329a39 [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 Yeh519c1672017-04-21 14:59:31 -070038HandleImporter CameraDeviceSession::sHandleImporter;
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());
Eino-Ville Talvala4ebf53f2017-05-24 15:05:56 -0700406 native_handle_close(handle);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800407 native_handle_delete(handle);
408 }
409 for (auto& buf : result.outputBuffers) {
410 if (buf.releaseFence.getNativeHandle() != nullptr) {
411 native_handle_t* handle = const_cast<native_handle_t*>(
412 buf.releaseFence.getNativeHandle());
Eino-Ville Talvala4ebf53f2017-05-24 15:05:56 -0700413 native_handle_close(handle);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800414 native_handle_delete(handle);
415 }
416 }
417 }
418 return;
419}
420
421void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
422 sendBatchBuffersLocked(batch, mStreamsToBatch);
423}
424
425void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
426 std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
427 size_t batchSize = 0;
428 for (int streamId : streams) {
429 auto it = batch->mBatchBufs.find(streamId);
430 if (it != batch->mBatchBufs.end()) {
431 InflightBatch::BufferBatch& bb = it->second;
432 if (bb.mDelivered) {
433 continue;
434 }
435 if (bb.mBuffers.size() > batchSize) {
436 batchSize = bb.mBuffers.size();
437 }
438 } else {
439 ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
440 return;
441 }
442 }
443
444 if (batchSize == 0) {
445 ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
446 for (int streamId : streams) {
447 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
448 bb.mDelivered = true;
449 }
450 return;
451 }
452
453 hidl_vec<CaptureResult> results;
454 results.resize(batchSize);
455 for (size_t i = 0; i < batchSize; i++) {
456 results[i].frameNumber = batch->mFirstFrame + i;
Yifan Hong993e3d02017-04-12 16:31:23 -0700457 results[i].fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800458 results[i].partialResult = 0; // 0 for buffer only results
459 results[i].inputBuffer.streamId = -1;
460 results[i].inputBuffer.bufferId = 0;
461 results[i].inputBuffer.buffer = nullptr;
462 std::vector<StreamBuffer> outBufs;
463 for (int streamId : streams) {
464 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
465 if (bb.mDelivered) {
466 continue;
467 }
468 if (i < bb.mBuffers.size()) {
469 outBufs.push_back(bb.mBuffers[i]);
470 }
471 }
472 results[i].outputBuffers = outBufs;
473 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700474 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */false);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800475 freeReleaseFences(results);
476 for (int streamId : streams) {
477 InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
478 bb.mDelivered = true;
479 bb.mBuffers.clear();
480 }
481}
482
483void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
484 std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
485 if (lastPartialResultIdx <= batch->mPartialResultProgress) {
486 // Result has been delivered. Return
487 ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
488 return;
489 }
490
491 std::vector<CaptureResult> results;
492 std::vector<uint32_t> toBeRemovedIdxes;
493 for (auto& pair : batch->mResultMds) {
494 uint32_t partialIdx = pair.first;
495 if (partialIdx > lastPartialResultIdx) {
496 continue;
497 }
498 toBeRemovedIdxes.push_back(partialIdx);
499 InflightBatch::MetadataBatch& mb = pair.second;
500 for (const auto& p : mb.mMds) {
501 CaptureResult result;
502 result.frameNumber = p.first;
503 result.result = std::move(p.second);
Yifan Hong993e3d02017-04-12 16:31:23 -0700504 result.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800505 result.inputBuffer.streamId = -1;
506 result.inputBuffer.bufferId = 0;
507 result.inputBuffer.buffer = nullptr;
508 result.partialResult = partialIdx;
509 results.push_back(std::move(result));
510 }
511 mb.mMds.clear();
512 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700513 hidl_vec<CaptureResult> hResults;
514 hResults.setToExternal(results.data(), results.size());
515 invokeProcessCaptureResultCallback(hResults, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800516 batch->mPartialResultProgress = lastPartialResultIdx;
517 for (uint32_t partialIdx : toBeRemovedIdxes) {
518 batch->mResultMds.erase(partialIdx);
519 }
520}
521
522void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
523 mCallback->notify({msg});
524 return;
525}
526
527void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
528 uint32_t frameNumber;
529 if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
530 frameNumber = msg.msg.shutter.frameNumber;
531 } else {
532 frameNumber = msg.msg.error.frameNumber;
533 }
534
535 auto pair = getBatch(frameNumber);
536 int batchIdx = pair.first;
537 if (batchIdx == NOT_BATCHED) {
538 notifySingleMsg(msg);
539 return;
540 }
541
542 // When error happened, stop batching for all batches earlier
543 if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
544 Mutex::Autolock _l(mLock);
545 for (int i = 0; i <= batchIdx; i++) {
546 // Send batched data up
547 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
548 {
549 Mutex::Autolock _l(batch->mLock);
550 sendBatchShutterCbsLocked(batch);
551 sendBatchBuffersLocked(batch);
552 sendBatchMetadataLocked(batch, mNumPartialResults);
553 if (!batch->allDelivered()) {
554 ALOGE("%s: error: some batch data not sent back to framework!",
555 __FUNCTION__);
556 }
557 batch->mRemoved = true;
558 }
559 mInflightBatches.pop_front();
560 }
561 // Send the error up
562 notifySingleMsg(msg);
563 return;
564 }
565 // Queue shutter callbacks for future delivery
566 std::shared_ptr<InflightBatch> batch = pair.second;
567 {
568 Mutex::Autolock _l(batch->mLock);
569 // Check if the batch is removed (mostly by notify error) before lock was acquired
570 if (batch->mRemoved) {
571 // Fall back to non-batch path
572 notifySingleMsg(msg);
573 return;
574 }
575
576 batch->mShutterMsgs.push_back(msg);
577 if (frameNumber == batch->mLastFrame) {
578 sendBatchShutterCbsLocked(batch);
579 }
580 } // end of batch lock scope
581
582 // see if the batch is complete
583 if (frameNumber == batch->mLastFrame) {
584 checkAndRemoveFirstBatch();
585 }
586}
587
Yifan Hong993e3d02017-04-12 16:31:23 -0700588void CameraDeviceSession::ResultBatcher::invokeProcessCaptureResultCallback(
589 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
590 if (mProcessCaptureResultLock.tryLock() != OK) {
Shuzhen Wang20786772017-05-25 10:34:13 -0700591 ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
Yifan Hong993e3d02017-04-12 16:31:23 -0700592 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
593 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
594 __FUNCTION__);
595 return;
596 }
597 }
598 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
599 for (CaptureResult &result : results) {
600 if (result.result.size() > 0) {
601 if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
602 result.fmqResultSize = result.result.size();
603 result.result.resize(0);
604 } else {
605 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
606 result.fmqResultSize = 0;
607 }
608 }
609 }
610 }
611 mCallback->processCaptureResult(results);
612 mProcessCaptureResultLock.unlock();
613}
614
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800615void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
616 hidl_vec<CaptureResult> results = {result};
Yifan Hong993e3d02017-04-12 16:31:23 -0700617 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800618 freeReleaseFences(results);
619 return;
620}
621
622void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
623 auto pair = getBatch(result.frameNumber);
624 int batchIdx = pair.first;
625 if (batchIdx == NOT_BATCHED) {
626 processOneCaptureResult(result);
627 return;
628 }
629 std::shared_ptr<InflightBatch> batch = pair.second;
630 {
631 Mutex::Autolock _l(batch->mLock);
632 // Check if the batch is removed (mostly by notify error) before lock was acquired
633 if (batch->mRemoved) {
634 // Fall back to non-batch path
635 processOneCaptureResult(result);
636 return;
637 }
638
639 // queue metadata
640 if (result.result.size() != 0) {
641 // Save a copy of metadata
642 batch->mResultMds[result.partialResult].mMds.push_back(
643 std::make_pair(result.frameNumber, result.result));
644 }
645
646 // queue buffer
647 std::vector<int> filledStreams;
648 std::vector<StreamBuffer> nonBatchedBuffers;
649 for (auto& buffer : result.outputBuffers) {
650 auto it = batch->mBatchBufs.find(buffer.streamId);
651 if (it != batch->mBatchBufs.end()) {
652 InflightBatch::BufferBatch& bb = it->second;
653 bb.mBuffers.push_back(buffer);
654 filledStreams.push_back(buffer.streamId);
655 } else {
656 nonBatchedBuffers.push_back(buffer);
657 }
658 }
659
660 // send non-batched buffers up
661 if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
662 CaptureResult nonBatchedResult;
663 nonBatchedResult.frameNumber = result.frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -0700664 nonBatchedResult.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800665 nonBatchedResult.outputBuffers = nonBatchedBuffers;
666 nonBatchedResult.inputBuffer = result.inputBuffer;
667 nonBatchedResult.partialResult = 0; // 0 for buffer only results
668 processOneCaptureResult(nonBatchedResult);
669 }
670
671 if (result.frameNumber == batch->mLastFrame) {
672 // Send data up
673 if (result.partialResult > 0) {
674 sendBatchMetadataLocked(batch, result.partialResult);
675 }
676 // send buffer up
677 if (filledStreams.size() > 0) {
678 sendBatchBuffersLocked(batch, filledStreams);
679 }
680 }
681 } // end of batch lock scope
682
683 // see if the batch is complete
684 if (result.frameNumber == batch->mLastFrame) {
685 checkAndRemoveFirstBatch();
686 }
687}
688
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700689// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
690Return<void> CameraDeviceSession::constructDefaultRequestSettings(
691 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
692 Status status = initStatus();
693 CameraMetadata outMetadata;
694 const camera_metadata_t *rawRequest;
695 if (status == Status::OK) {
696 ATRACE_BEGIN("camera3->construct_default_request_settings");
697 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
698 ATRACE_END();
699 if (rawRequest == nullptr) {
700 ALOGI("%s: template %d is not supported on this camera device",
701 __FUNCTION__, type);
702 status = Status::ILLEGAL_ARGUMENT;
703 } else {
Emilian Peeva13ac992017-04-10 12:02:17 +0100704 mOverridenRequest.clear();
705 mOverridenRequest.append(rawRequest);
706 // Derive some new keys for backward compatibility
707 if (mDerivePostRawSensKey && !mOverridenRequest.exists(
708 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST)) {
709 int32_t defaultBoost[1] = {100};
710 mOverridenRequest.update(
711 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
712 defaultBoost, 1);
713 const camera_metadata_t *metaBuffer =
714 mOverridenRequest.getAndLock();
715 convertToHidl(metaBuffer, &outMetadata);
716 mOverridenRequest.unlock(metaBuffer);
717 } else {
718 convertToHidl(rawRequest, &outMetadata);
719 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700720 }
721 }
722 _hidl_cb(status, outMetadata);
723 return Void();
724}
725
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100726/**
727 * Map Android N dataspace definitions back to Android M definitions, for
728 * use with HALv3.3 or older.
729 *
730 * Only map where correspondences exist, and otherwise preserve the value.
731 */
732android_dataspace CameraDeviceSession::mapToLegacyDataspace(
733 android_dataspace dataSpace) const {
734 if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
735 switch (dataSpace) {
736 case HAL_DATASPACE_V0_SRGB_LINEAR:
737 return HAL_DATASPACE_SRGB_LINEAR;
738 case HAL_DATASPACE_V0_SRGB:
739 return HAL_DATASPACE_SRGB;
740 case HAL_DATASPACE_V0_JFIF:
741 return HAL_DATASPACE_JFIF;
742 case HAL_DATASPACE_V0_BT601_625:
743 return HAL_DATASPACE_BT601_625;
744 case HAL_DATASPACE_V0_BT601_525:
745 return HAL_DATASPACE_BT601_525;
746 case HAL_DATASPACE_V0_BT709:
747 return HAL_DATASPACE_BT709;
748 default:
749 return dataSpace;
750 }
751 }
752
753 return dataSpace;
754}
755
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700756Return<void> CameraDeviceSession::configureStreams(
757 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
758 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800759 HalStreamConfiguration outStreams;
760
761 // hold the inflight lock for entire configureStreams scope since there must not be any
762 // inflight request/results during stream configuration.
763 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700764 if (!mInflightBuffers.empty()) {
765 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
766 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800767 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
768 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700769 }
770
Emilian Peevcf581372017-04-07 13:53:10 +0100771 if (!mInflightAETriggerOverrides.empty()) {
772 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
773 " trigger overrides!", __FUNCTION__,
774 mInflightAETriggerOverrides.size());
775 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
776 return Void();
777 }
778
Emilian Peeva13ac992017-04-10 12:02:17 +0100779 if (!mInflightRawBoostPresent.empty()) {
780 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
781 " boost overrides!", __FUNCTION__,
782 mInflightRawBoostPresent.size());
783 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
784 return Void();
785 }
786
Emilian Peev98014ff2017-02-02 16:20:12 +0000787 if (status != Status::OK) {
788 _hidl_cb(status, outStreams);
789 return Void();
790 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800791
Emilian Peev98014ff2017-02-02 16:20:12 +0000792 camera3_stream_configuration_t stream_list;
793 hidl_vec<camera3_stream_t*> streams;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800794
Emilian Peev98014ff2017-02-02 16:20:12 +0000795 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
796 stream_list.num_streams = requestedConfiguration.streams.size();
797 streams.resize(stream_list.num_streams);
798 stream_list.streams = streams.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700799
Emilian Peev98014ff2017-02-02 16:20:12 +0000800 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
801 int id = requestedConfiguration.streams[i].id;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700802
Emilian Peev98014ff2017-02-02 16:20:12 +0000803 if (mStreamMap.count(id) == 0) {
804 Camera3Stream stream;
805 convertFromHidl(requestedConfiguration.streams[i], &stream);
806 mStreamMap[id] = stream;
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100807 mStreamMap[id].data_space = mapToLegacyDataspace(
808 mStreamMap[id].data_space);
Emilian Peev98014ff2017-02-02 16:20:12 +0000809 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
810 } else {
811 // width/height/format must not change, but usage/rotation might need to change
812 if (mStreamMap[id].stream_type !=
813 (int) requestedConfiguration.streams[i].streamType ||
814 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
815 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
816 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100817 mStreamMap[id].data_space !=
818 mapToLegacyDataspace( static_cast<android_dataspace_t> (
819 requestedConfiguration.streams[i].dataSpace))) {
Emilian Peev98014ff2017-02-02 16:20:12 +0000820 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
821 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
822 return Void();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800823 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000824 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
Yin-Chia Yehc25c54f2017-04-04 13:00:35 -0700825 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700826 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000827 streams[i] = &mStreamMap[id];
828 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700829
Emilian Peev98014ff2017-02-02 16:20:12 +0000830 ATRACE_BEGIN("camera3->configure_streams");
831 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
832 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700833
Emilian Peev98014ff2017-02-02 16:20:12 +0000834 // In case Hal returns error most likely it was not able to release
835 // the corresponding resources of the deleted streams.
836 if (ret == OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800837 // delete unused streams, note we do this after adding new streams to ensure new stream
838 // will not have the same address as deleted stream, and HAL has a chance to reference
839 // the to be deleted stream in configure_streams call
840 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
841 int id = it->first;
842 bool found = false;
843 for (const auto& stream : requestedConfiguration.streams) {
844 if (id == stream.id) {
845 found = true;
846 break;
847 }
848 }
849 if (!found) {
850 // Unmap all buffers of deleted stream
Emilian Peev98014ff2017-02-02 16:20:12 +0000851 // in case the configuration call succeeds and HAL
852 // is able to release the corresponding resources too.
853 cleanupBuffersLocked(id);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800854 it = mStreamMap.erase(it);
855 } else {
856 ++it;
857 }
858 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800859
860 // Track video streams
861 mVideoStreamIds.clear();
862 for (const auto& stream : requestedConfiguration.streams) {
863 if (stream.streamType == StreamType::OUTPUT &&
Chia-I Wu79d13ff2017-03-31 12:48:11 -0700864 stream.usage &
865 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800866 mVideoStreamIds.push_back(stream.id);
867 }
868 }
869 mResultBatcher.setBatchedStreams(mVideoStreamIds);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700870 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000871
872 if (ret == -EINVAL) {
873 status = Status::ILLEGAL_ARGUMENT;
874 } else if (ret != OK) {
875 status = Status::INTERNAL_ERROR;
876 } else {
877 convertToHidl(stream_list, &outStreams);
878 }
879
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700880 _hidl_cb(status, outStreams);
881 return Void();
882}
883
Emilian Peev98014ff2017-02-02 16:20:12 +0000884// Needs to get called after acquiring 'mInflightLock'
885void CameraDeviceSession::cleanupBuffersLocked(int id) {
886 for (auto& pair : mCirculatingBuffers.at(id)) {
887 sHandleImporter.freeBuffer(pair.second);
888 }
889 mCirculatingBuffers[id].clear();
890 mCirculatingBuffers.erase(id);
891}
892
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700893void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
894 Mutex::Autolock _l(mInflightLock);
895 for (auto& cache : cachesToRemove) {
896 auto cbsIt = mCirculatingBuffers.find(cache.streamId);
897 if (cbsIt == mCirculatingBuffers.end()) {
898 // The stream could have been removed
899 continue;
900 }
901 CirculatingBuffers& cbs = cbsIt->second;
902 auto it = cbs.find(cache.bufferId);
903 if (it != cbs.end()) {
904 sHandleImporter.freeBuffer(it->second);
905 cbs.erase(it);
906 } else {
907 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
908 __FUNCTION__, cache.streamId, cache.bufferId);
909 }
910 }
911}
912
Yifan Hong1192e1d2017-04-11 14:45:00 -0700913Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
914 getCaptureRequestMetadataQueue_cb _hidl_cb) {
915 _hidl_cb(*mRequestMetadataQueue->getDesc());
916 return Void();
917}
918
Yifan Hong993e3d02017-04-12 16:31:23 -0700919Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
920 getCaptureResultMetadataQueue_cb _hidl_cb) {
921 _hidl_cb(*mResultMetadataQueue->getDesc());
922 return Void();
923}
924
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800925Return<void> CameraDeviceSession::processCaptureRequest(
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700926 const hidl_vec<CaptureRequest>& requests,
927 const hidl_vec<BufferCache>& cachesToRemove,
928 processCaptureRequest_cb _hidl_cb) {
929 updateBufferCaches(cachesToRemove);
930
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800931 uint32_t numRequestProcessed = 0;
932 Status s = Status::OK;
933 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
934 s = processOneCaptureRequest(requests[i]);
935 if (s != Status::OK) {
936 break;
937 }
938 }
939
940 if (s == Status::OK && requests.size() > 1) {
941 mResultBatcher.registerBatch(requests);
942 }
943
944 _hidl_cb(s, numRequestProcessed);
945 return Void();
946}
947
948Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700949 Status status = initStatus();
950 if (status != Status::OK) {
951 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
952 return status;
953 }
954
955 camera3_capture_request_t halRequest;
956 halRequest.frame_number = request.frameNumber;
Yifan Hong1192e1d2017-04-11 14:45:00 -0700957
958 bool converted = true;
959 CameraMetadata settingsFmq; // settings from FMQ
960 if (request.fmqSettingsSize > 0) {
961 // non-blocking read; client must write metadata before calling
962 // processOneCaptureRequest
963 settingsFmq.resize(request.fmqSettingsSize);
964 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
965 if (read) {
966 converted = convertFromHidl(settingsFmq, &halRequest.settings);
967 } else {
968 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
969 converted = false;
970 }
971 } else {
972 converted = convertFromHidl(request.settings, &halRequest.settings);
973 }
974
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700975 if (!converted) {
976 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
977 return Status::INTERNAL_ERROR;
978 }
979
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800980 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700981 hidl_vec<int> allFences;
982 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800983 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700984 size_t numOutputBufs = request.outputBuffers.size();
985 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800986 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700987 if (status != Status::OK) {
988 return status;
989 }
990
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700991 hidl_vec<camera3_stream_buffer_t> outHalBufs;
992 outHalBufs.resize(numOutputBufs);
Emilian Peevcf581372017-04-07 13:53:10 +0100993 bool aeCancelTriggerNeeded = false;
994 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800995 {
996 Mutex::Autolock _l(mInflightLock);
997 if (hasInputBuf) {
998 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
999 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
1000 convertFromHidl(
1001 allBufPtrs[numOutputBufs], request.inputBuffer.status,
1002 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
1003 &bufCache);
1004 halRequest.input_buffer = &bufCache;
1005 } else {
1006 halRequest.input_buffer = nullptr;
1007 }
1008
1009 halRequest.num_output_buffers = numOutputBufs;
1010 for (size_t i = 0; i < numOutputBufs; i++) {
1011 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1012 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
1013 convertFromHidl(
1014 allBufPtrs[i], request.outputBuffers[i].status,
1015 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
1016 &bufCache);
1017 outHalBufs[i] = bufCache;
1018 }
1019 halRequest.output_buffers = outHalBufs.data();
Emilian Peevcf581372017-04-07 13:53:10 +01001020
1021 AETriggerCancelOverride triggerOverride;
1022 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
1023 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
1024 if (aeCancelTriggerNeeded) {
1025 mInflightAETriggerOverrides[halRequest.frame_number] =
1026 triggerOverride;
1027 halRequest.settings = settingsOverride.getAndLock();
1028 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001029 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001030
1031 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
1032 ATRACE_BEGIN("camera3->process_capture_request");
1033 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
1034 ATRACE_END();
Emilian Peevcf581372017-04-07 13:53:10 +01001035 if (aeCancelTriggerNeeded) {
1036 settingsOverride.unlock(halRequest.settings);
1037 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001038 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001039 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001040 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
1041
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001042 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001043 if (hasInputBuf) {
1044 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
1045 mInflightBuffers.erase(key);
1046 }
1047 for (size_t i = 0; i < numOutputBufs; i++) {
1048 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1049 mInflightBuffers.erase(key);
1050 }
Emilian Peevcf581372017-04-07 13:53:10 +01001051 if (aeCancelTriggerNeeded) {
1052 mInflightAETriggerOverrides.erase(request.frameNumber);
1053 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001054 return Status::INTERNAL_ERROR;
1055 }
1056
1057 return Status::OK;
1058}
1059
1060Return<Status> CameraDeviceSession::flush() {
1061 Status status = initStatus();
1062 if (status == Status::OK) {
1063 // Flush is always supported on device 3.1 or later
1064 status_t ret = mDevice->ops->flush(mDevice);
1065 if (ret != OK) {
1066 status = Status::INTERNAL_ERROR;
1067 }
1068 }
1069 return status;
1070}
1071
1072Return<void> CameraDeviceSession::close() {
1073 Mutex::Autolock _l(mStateLock);
1074 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001075 {
1076 Mutex::Autolock _l(mInflightLock);
1077 if (!mInflightBuffers.empty()) {
1078 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
1079 __FUNCTION__, mInflightBuffers.size());
1080 }
Emilian Peevcf581372017-04-07 13:53:10 +01001081 if (!mInflightAETriggerOverrides.empty()) {
1082 ALOGE("%s: trying to close while there are still %zu inflight "
1083 "trigger overrides!", __FUNCTION__,
1084 mInflightAETriggerOverrides.size());
1085 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001086 if (!mInflightRawBoostPresent.empty()) {
1087 ALOGE("%s: trying to close while there are still %zu inflight "
1088 " RAW boost overrides!", __FUNCTION__,
1089 mInflightRawBoostPresent.size());
1090 }
Emilian Peevcf581372017-04-07 13:53:10 +01001091
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001092 }
1093
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001094 ATRACE_BEGIN("camera3->close");
1095 mDevice->common.close(&mDevice->common);
1096 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001097
1098 // free all imported buffers
1099 for(auto& pair : mCirculatingBuffers) {
1100 CirculatingBuffers& buffers = pair.second;
1101 for (auto& p2 : buffers) {
1102 sHandleImporter.freeBuffer(p2.second);
1103 }
1104 }
1105
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001106 mClosed = true;
1107 }
1108 return Void();
1109}
1110
1111/**
1112 * Static callback forwarding methods from HAL to instance
1113 */
1114void CameraDeviceSession::sProcessCaptureResult(
1115 const camera3_callback_ops *cb,
1116 const camera3_capture_result *hal_result) {
1117 CameraDeviceSession *d =
1118 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1119
1120 uint32_t frameNumber = hal_result->frame_number;
1121 bool hasInputBuf = (hal_result->input_buffer != nullptr);
1122 size_t numOutputBufs = hal_result->num_output_buffers;
1123 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001124 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001125 Mutex::Autolock _l(d->mInflightLock);
1126 if (hasInputBuf) {
1127 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1128 // validate if buffer is inflight
1129 auto key = std::make_pair(streamId, frameNumber);
1130 if (d->mInflightBuffers.count(key) != 1) {
1131 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
1132 __FUNCTION__, streamId, frameNumber);
1133 return;
1134 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001135 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001136
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001137 for (size_t i = 0; i < numOutputBufs; i++) {
1138 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1139 // validate if buffer is inflight
1140 auto key = std::make_pair(streamId, frameNumber);
1141 if (d->mInflightBuffers.count(key) != 1) {
1142 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
1143 __FUNCTION__, streamId, frameNumber);
1144 return;
1145 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001146 }
1147 }
1148 // We don't need to validate/import fences here since we will be passing them to camera service
1149 // within the scope of this function
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001150 CaptureResult result;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001151 result.frameNumber = frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -07001152 result.fmqResultSize = 0;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001153 result.partialResult = hal_result->partial_result;
1154 convertToHidl(hal_result->result, &result.result);
Emilian Peevcf581372017-04-07 13:53:10 +01001155 if (nullptr != hal_result->result) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001156 bool resultOverriden = false;
Emilian Peevcf581372017-04-07 13:53:10 +01001157 Mutex::Autolock _l(d->mInflightLock);
Emilian Peeva13ac992017-04-10 12:02:17 +01001158
1159 // Derive some new keys for backward compatibility
1160 if (d->mDerivePostRawSensKey) {
1161 camera_metadata_ro_entry entry;
1162 if (find_camera_metadata_ro_entry(hal_result->result,
1163 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, &entry) == 0) {
1164 d->mInflightRawBoostPresent[frameNumber] = true;
1165 } else {
1166 auto entry = d->mInflightRawBoostPresent.find(frameNumber);
1167 if (d->mInflightRawBoostPresent.end() == entry) {
1168 d->mInflightRawBoostPresent[frameNumber] = false;
1169 }
1170 }
1171
1172 if ((hal_result->partial_result == d->mNumPartialResults)) {
1173 if (!d->mInflightRawBoostPresent[frameNumber]) {
1174 if (!resultOverriden) {
1175 d->mOverridenResult.clear();
1176 d->mOverridenResult.append(hal_result->result);
1177 resultOverriden = true;
1178 }
1179 int32_t defaultBoost[1] = {100};
1180 d->mOverridenResult.update(
1181 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
1182 defaultBoost, 1);
1183 }
1184
1185 d->mInflightRawBoostPresent.erase(frameNumber);
1186 }
1187 }
1188
Emilian Peevcf581372017-04-07 13:53:10 +01001189 auto entry = d->mInflightAETriggerOverrides.find(frameNumber);
1190 if (d->mInflightAETriggerOverrides.end() != entry) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001191 if (!resultOverriden) {
1192 d->mOverridenResult.clear();
1193 d->mOverridenResult.append(hal_result->result);
1194 resultOverriden = true;
1195 }
Emilian Peevcf581372017-04-07 13:53:10 +01001196 d->overrideResultForPrecaptureCancelLocked(entry->second,
1197 &d->mOverridenResult);
Emilian Peevcf581372017-04-07 13:53:10 +01001198 if (hal_result->partial_result == d->mNumPartialResults) {
1199 d->mInflightAETriggerOverrides.erase(frameNumber);
1200 }
1201 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001202
1203 if (resultOverriden) {
1204 const camera_metadata_t *metaBuffer =
1205 d->mOverridenResult.getAndLock();
1206 convertToHidl(metaBuffer, &result.result);
1207 d->mOverridenResult.unlock(metaBuffer);
1208 }
Emilian Peevcf581372017-04-07 13:53:10 +01001209 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001210 if (hasInputBuf) {
1211 result.inputBuffer.streamId =
1212 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1213 result.inputBuffer.buffer = nullptr;
1214 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
1215 // skip acquire fence since it's no use to camera service
1216 if (hal_result->input_buffer->release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001217 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1218 handle->data[0] = hal_result->input_buffer->release_fence;
1219 result.inputBuffer.releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001220 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001221 result.inputBuffer.releaseFence = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001222 }
1223 } else {
1224 result.inputBuffer.streamId = -1;
1225 }
1226
1227 result.outputBuffers.resize(numOutputBufs);
1228 for (size_t i = 0; i < numOutputBufs; i++) {
1229 result.outputBuffers[i].streamId =
1230 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1231 result.outputBuffers[i].buffer = nullptr;
1232 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
1233 // skip acquire fence since it's of no use to camera service
1234 if (hal_result->output_buffers[i].release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001235 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1236 handle->data[0] = hal_result->output_buffers[i].release_fence;
1237 result.outputBuffers[i].releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001238 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001239 result.outputBuffers[i].releaseFence = nullptr;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001240 }
1241 }
1242
1243 // Free inflight record/fences.
1244 // Do this before call back to camera service because camera service might jump to
1245 // configure_streams right after the processCaptureResult call so we need to finish
1246 // updating inflight queues first
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001247 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001248 Mutex::Autolock _l(d->mInflightLock);
1249 if (hasInputBuf) {
1250 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1251 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001252 d->mInflightBuffers.erase(key);
1253 }
1254
1255 for (size_t i = 0; i < numOutputBufs; i++) {
1256 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1257 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001258 d->mInflightBuffers.erase(key);
1259 }
1260
1261 if (d->mInflightBuffers.empty()) {
1262 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001263 }
1264 }
1265
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001266 d->mResultBatcher.processCaptureResult(result);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001267}
1268
1269void CameraDeviceSession::sNotify(
1270 const camera3_callback_ops *cb,
1271 const camera3_notify_msg *msg) {
1272 CameraDeviceSession *d =
1273 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1274 NotifyMsg hidlMsg;
1275 convertToHidl(msg, &hidlMsg);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001276
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001277 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
1278 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001279 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
1280 ALOGE("%s: unknown stream ID %d reports an error!",
1281 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001282 return;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001283 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001284 }
Emilian Peevcf581372017-04-07 13:53:10 +01001285
1286 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
1287 switch (hidlMsg.msg.error.errorCode) {
1288 case ErrorCode::ERROR_DEVICE:
1289 case ErrorCode::ERROR_REQUEST:
1290 case ErrorCode::ERROR_RESULT: {
1291 Mutex::Autolock _l(d->mInflightLock);
1292 auto entry = d->mInflightAETriggerOverrides.find(
1293 hidlMsg.msg.error.frameNumber);
1294 if (d->mInflightAETriggerOverrides.end() != entry) {
1295 d->mInflightAETriggerOverrides.erase(
1296 hidlMsg.msg.error.frameNumber);
1297 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001298
1299 auto boostEntry = d->mInflightRawBoostPresent.find(
1300 hidlMsg.msg.error.frameNumber);
1301 if (d->mInflightRawBoostPresent.end() != boostEntry) {
1302 d->mInflightRawBoostPresent.erase(
1303 hidlMsg.msg.error.frameNumber);
1304 }
1305
Emilian Peevcf581372017-04-07 13:53:10 +01001306 }
1307 break;
1308 case ErrorCode::ERROR_BUFFER:
1309 default:
1310 break;
1311 }
1312
1313 }
1314
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001315 d->mResultBatcher.notify(hidlMsg);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001316}
1317
1318} // namespace implementation
1319} // namespace V3_2
1320} // namespace device
1321} // namespace camera
1322} // namespace hardware
1323} // namespace android