blob: bad406f8cc604fdd5a59afd9b9b439b88c9f73bc [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) {
591 ALOGW("%s: previous call is not finished! waiting 1s...",
592 __FUNCTION__);
593 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
594 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
595 __FUNCTION__);
596 return;
597 }
598 }
599 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
600 for (CaptureResult &result : results) {
601 if (result.result.size() > 0) {
602 if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
603 result.fmqResultSize = result.result.size();
604 result.result.resize(0);
605 } else {
606 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
607 result.fmqResultSize = 0;
608 }
609 }
610 }
611 }
612 mCallback->processCaptureResult(results);
613 mProcessCaptureResultLock.unlock();
614}
615
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800616void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
617 hidl_vec<CaptureResult> results = {result};
Yifan Hong993e3d02017-04-12 16:31:23 -0700618 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800619 freeReleaseFences(results);
620 return;
621}
622
623void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
624 auto pair = getBatch(result.frameNumber);
625 int batchIdx = pair.first;
626 if (batchIdx == NOT_BATCHED) {
627 processOneCaptureResult(result);
628 return;
629 }
630 std::shared_ptr<InflightBatch> batch = pair.second;
631 {
632 Mutex::Autolock _l(batch->mLock);
633 // Check if the batch is removed (mostly by notify error) before lock was acquired
634 if (batch->mRemoved) {
635 // Fall back to non-batch path
636 processOneCaptureResult(result);
637 return;
638 }
639
640 // queue metadata
641 if (result.result.size() != 0) {
642 // Save a copy of metadata
643 batch->mResultMds[result.partialResult].mMds.push_back(
644 std::make_pair(result.frameNumber, result.result));
645 }
646
647 // queue buffer
648 std::vector<int> filledStreams;
649 std::vector<StreamBuffer> nonBatchedBuffers;
650 for (auto& buffer : result.outputBuffers) {
651 auto it = batch->mBatchBufs.find(buffer.streamId);
652 if (it != batch->mBatchBufs.end()) {
653 InflightBatch::BufferBatch& bb = it->second;
654 bb.mBuffers.push_back(buffer);
655 filledStreams.push_back(buffer.streamId);
656 } else {
657 nonBatchedBuffers.push_back(buffer);
658 }
659 }
660
661 // send non-batched buffers up
662 if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
663 CaptureResult nonBatchedResult;
664 nonBatchedResult.frameNumber = result.frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -0700665 nonBatchedResult.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800666 nonBatchedResult.outputBuffers = nonBatchedBuffers;
667 nonBatchedResult.inputBuffer = result.inputBuffer;
668 nonBatchedResult.partialResult = 0; // 0 for buffer only results
669 processOneCaptureResult(nonBatchedResult);
670 }
671
672 if (result.frameNumber == batch->mLastFrame) {
673 // Send data up
674 if (result.partialResult > 0) {
675 sendBatchMetadataLocked(batch, result.partialResult);
676 }
677 // send buffer up
678 if (filledStreams.size() > 0) {
679 sendBatchBuffersLocked(batch, filledStreams);
680 }
681 }
682 } // end of batch lock scope
683
684 // see if the batch is complete
685 if (result.frameNumber == batch->mLastFrame) {
686 checkAndRemoveFirstBatch();
687 }
688}
689
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700690// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
691Return<void> CameraDeviceSession::constructDefaultRequestSettings(
692 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
693 Status status = initStatus();
694 CameraMetadata outMetadata;
695 const camera_metadata_t *rawRequest;
696 if (status == Status::OK) {
697 ATRACE_BEGIN("camera3->construct_default_request_settings");
698 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
699 ATRACE_END();
700 if (rawRequest == nullptr) {
701 ALOGI("%s: template %d is not supported on this camera device",
702 __FUNCTION__, type);
703 status = Status::ILLEGAL_ARGUMENT;
704 } else {
Emilian Peeva13ac992017-04-10 12:02:17 +0100705 mOverridenRequest.clear();
706 mOverridenRequest.append(rawRequest);
707 // Derive some new keys for backward compatibility
708 if (mDerivePostRawSensKey && !mOverridenRequest.exists(
709 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST)) {
710 int32_t defaultBoost[1] = {100};
711 mOverridenRequest.update(
712 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
713 defaultBoost, 1);
714 const camera_metadata_t *metaBuffer =
715 mOverridenRequest.getAndLock();
716 convertToHidl(metaBuffer, &outMetadata);
717 mOverridenRequest.unlock(metaBuffer);
718 } else {
719 convertToHidl(rawRequest, &outMetadata);
720 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700721 }
722 }
723 _hidl_cb(status, outMetadata);
724 return Void();
725}
726
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100727/**
728 * Map Android N dataspace definitions back to Android M definitions, for
729 * use with HALv3.3 or older.
730 *
731 * Only map where correspondences exist, and otherwise preserve the value.
732 */
733android_dataspace CameraDeviceSession::mapToLegacyDataspace(
734 android_dataspace dataSpace) const {
735 if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
736 switch (dataSpace) {
737 case HAL_DATASPACE_V0_SRGB_LINEAR:
738 return HAL_DATASPACE_SRGB_LINEAR;
739 case HAL_DATASPACE_V0_SRGB:
740 return HAL_DATASPACE_SRGB;
741 case HAL_DATASPACE_V0_JFIF:
742 return HAL_DATASPACE_JFIF;
743 case HAL_DATASPACE_V0_BT601_625:
744 return HAL_DATASPACE_BT601_625;
745 case HAL_DATASPACE_V0_BT601_525:
746 return HAL_DATASPACE_BT601_525;
747 case HAL_DATASPACE_V0_BT709:
748 return HAL_DATASPACE_BT709;
749 default:
750 return dataSpace;
751 }
752 }
753
754 return dataSpace;
755}
756
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700757Return<void> CameraDeviceSession::configureStreams(
758 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
759 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800760 HalStreamConfiguration outStreams;
761
762 // hold the inflight lock for entire configureStreams scope since there must not be any
763 // inflight request/results during stream configuration.
764 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700765 if (!mInflightBuffers.empty()) {
766 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
767 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800768 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
769 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700770 }
771
Emilian Peevcf581372017-04-07 13:53:10 +0100772 if (!mInflightAETriggerOverrides.empty()) {
773 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
774 " trigger overrides!", __FUNCTION__,
775 mInflightAETriggerOverrides.size());
776 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
777 return Void();
778 }
779
Emilian Peeva13ac992017-04-10 12:02:17 +0100780 if (!mInflightRawBoostPresent.empty()) {
781 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
782 " boost overrides!", __FUNCTION__,
783 mInflightRawBoostPresent.size());
784 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
785 return Void();
786 }
787
Emilian Peev98014ff2017-02-02 16:20:12 +0000788 if (status != Status::OK) {
789 _hidl_cb(status, outStreams);
790 return Void();
791 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800792
Emilian Peev98014ff2017-02-02 16:20:12 +0000793 camera3_stream_configuration_t stream_list;
794 hidl_vec<camera3_stream_t*> streams;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800795
Emilian Peev98014ff2017-02-02 16:20:12 +0000796 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
797 stream_list.num_streams = requestedConfiguration.streams.size();
798 streams.resize(stream_list.num_streams);
799 stream_list.streams = streams.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700800
Emilian Peev98014ff2017-02-02 16:20:12 +0000801 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
802 int id = requestedConfiguration.streams[i].id;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700803
Emilian Peev98014ff2017-02-02 16:20:12 +0000804 if (mStreamMap.count(id) == 0) {
805 Camera3Stream stream;
806 convertFromHidl(requestedConfiguration.streams[i], &stream);
807 mStreamMap[id] = stream;
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100808 mStreamMap[id].data_space = mapToLegacyDataspace(
809 mStreamMap[id].data_space);
Emilian Peev98014ff2017-02-02 16:20:12 +0000810 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
811 } else {
812 // width/height/format must not change, but usage/rotation might need to change
813 if (mStreamMap[id].stream_type !=
814 (int) requestedConfiguration.streams[i].streamType ||
815 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
816 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
817 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100818 mStreamMap[id].data_space !=
819 mapToLegacyDataspace( static_cast<android_dataspace_t> (
820 requestedConfiguration.streams[i].dataSpace))) {
Emilian Peev98014ff2017-02-02 16:20:12 +0000821 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
822 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
823 return Void();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800824 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000825 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
Yin-Chia Yehc25c54f2017-04-04 13:00:35 -0700826 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700827 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000828 streams[i] = &mStreamMap[id];
829 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700830
Emilian Peev98014ff2017-02-02 16:20:12 +0000831 ATRACE_BEGIN("camera3->configure_streams");
832 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
833 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700834
Emilian Peev98014ff2017-02-02 16:20:12 +0000835 // In case Hal returns error most likely it was not able to release
836 // the corresponding resources of the deleted streams.
837 if (ret == OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800838 // delete unused streams, note we do this after adding new streams to ensure new stream
839 // will not have the same address as deleted stream, and HAL has a chance to reference
840 // the to be deleted stream in configure_streams call
841 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
842 int id = it->first;
843 bool found = false;
844 for (const auto& stream : requestedConfiguration.streams) {
845 if (id == stream.id) {
846 found = true;
847 break;
848 }
849 }
850 if (!found) {
851 // Unmap all buffers of deleted stream
Emilian Peev98014ff2017-02-02 16:20:12 +0000852 // in case the configuration call succeeds and HAL
853 // is able to release the corresponding resources too.
854 cleanupBuffersLocked(id);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800855 it = mStreamMap.erase(it);
856 } else {
857 ++it;
858 }
859 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800860
861 // Track video streams
862 mVideoStreamIds.clear();
863 for (const auto& stream : requestedConfiguration.streams) {
864 if (stream.streamType == StreamType::OUTPUT &&
Chia-I Wu79d13ff2017-03-31 12:48:11 -0700865 stream.usage &
866 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800867 mVideoStreamIds.push_back(stream.id);
868 }
869 }
870 mResultBatcher.setBatchedStreams(mVideoStreamIds);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700871 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000872
873 if (ret == -EINVAL) {
874 status = Status::ILLEGAL_ARGUMENT;
875 } else if (ret != OK) {
876 status = Status::INTERNAL_ERROR;
877 } else {
878 convertToHidl(stream_list, &outStreams);
879 }
880
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700881 _hidl_cb(status, outStreams);
882 return Void();
883}
884
Emilian Peev98014ff2017-02-02 16:20:12 +0000885// Needs to get called after acquiring 'mInflightLock'
886void CameraDeviceSession::cleanupBuffersLocked(int id) {
887 for (auto& pair : mCirculatingBuffers.at(id)) {
888 sHandleImporter.freeBuffer(pair.second);
889 }
890 mCirculatingBuffers[id].clear();
891 mCirculatingBuffers.erase(id);
892}
893
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700894void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
895 Mutex::Autolock _l(mInflightLock);
896 for (auto& cache : cachesToRemove) {
897 auto cbsIt = mCirculatingBuffers.find(cache.streamId);
898 if (cbsIt == mCirculatingBuffers.end()) {
899 // The stream could have been removed
900 continue;
901 }
902 CirculatingBuffers& cbs = cbsIt->second;
903 auto it = cbs.find(cache.bufferId);
904 if (it != cbs.end()) {
905 sHandleImporter.freeBuffer(it->second);
906 cbs.erase(it);
907 } else {
908 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
909 __FUNCTION__, cache.streamId, cache.bufferId);
910 }
911 }
912}
913
Yifan Hong1192e1d2017-04-11 14:45:00 -0700914Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
915 getCaptureRequestMetadataQueue_cb _hidl_cb) {
916 _hidl_cb(*mRequestMetadataQueue->getDesc());
917 return Void();
918}
919
Yifan Hong993e3d02017-04-12 16:31:23 -0700920Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
921 getCaptureResultMetadataQueue_cb _hidl_cb) {
922 _hidl_cb(*mResultMetadataQueue->getDesc());
923 return Void();
924}
925
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800926Return<void> CameraDeviceSession::processCaptureRequest(
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700927 const hidl_vec<CaptureRequest>& requests,
928 const hidl_vec<BufferCache>& cachesToRemove,
929 processCaptureRequest_cb _hidl_cb) {
930 updateBufferCaches(cachesToRemove);
931
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800932 uint32_t numRequestProcessed = 0;
933 Status s = Status::OK;
934 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
935 s = processOneCaptureRequest(requests[i]);
936 if (s != Status::OK) {
937 break;
938 }
939 }
940
941 if (s == Status::OK && requests.size() > 1) {
942 mResultBatcher.registerBatch(requests);
943 }
944
945 _hidl_cb(s, numRequestProcessed);
946 return Void();
947}
948
949Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700950 Status status = initStatus();
951 if (status != Status::OK) {
952 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
953 return status;
954 }
955
956 camera3_capture_request_t halRequest;
957 halRequest.frame_number = request.frameNumber;
Yifan Hong1192e1d2017-04-11 14:45:00 -0700958
959 bool converted = true;
960 CameraMetadata settingsFmq; // settings from FMQ
961 if (request.fmqSettingsSize > 0) {
962 // non-blocking read; client must write metadata before calling
963 // processOneCaptureRequest
964 settingsFmq.resize(request.fmqSettingsSize);
965 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
966 if (read) {
967 converted = convertFromHidl(settingsFmq, &halRequest.settings);
968 } else {
969 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
970 converted = false;
971 }
972 } else {
973 converted = convertFromHidl(request.settings, &halRequest.settings);
974 }
975
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700976 if (!converted) {
977 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
978 return Status::INTERNAL_ERROR;
979 }
980
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800981 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700982 hidl_vec<int> allFences;
983 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800984 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700985 size_t numOutputBufs = request.outputBuffers.size();
986 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800987 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700988 if (status != Status::OK) {
989 return status;
990 }
991
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700992 hidl_vec<camera3_stream_buffer_t> outHalBufs;
993 outHalBufs.resize(numOutputBufs);
Emilian Peevcf581372017-04-07 13:53:10 +0100994 bool aeCancelTriggerNeeded = false;
995 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800996 {
997 Mutex::Autolock _l(mInflightLock);
998 if (hasInputBuf) {
999 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
1000 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
1001 convertFromHidl(
1002 allBufPtrs[numOutputBufs], request.inputBuffer.status,
1003 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
1004 &bufCache);
1005 halRequest.input_buffer = &bufCache;
1006 } else {
1007 halRequest.input_buffer = nullptr;
1008 }
1009
1010 halRequest.num_output_buffers = numOutputBufs;
1011 for (size_t i = 0; i < numOutputBufs; i++) {
1012 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1013 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
1014 convertFromHidl(
1015 allBufPtrs[i], request.outputBuffers[i].status,
1016 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
1017 &bufCache);
1018 outHalBufs[i] = bufCache;
1019 }
1020 halRequest.output_buffers = outHalBufs.data();
Emilian Peevcf581372017-04-07 13:53:10 +01001021
1022 AETriggerCancelOverride triggerOverride;
1023 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
1024 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
1025 if (aeCancelTriggerNeeded) {
1026 mInflightAETriggerOverrides[halRequest.frame_number] =
1027 triggerOverride;
1028 halRequest.settings = settingsOverride.getAndLock();
1029 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001030 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001031
1032 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
1033 ATRACE_BEGIN("camera3->process_capture_request");
1034 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
1035 ATRACE_END();
Emilian Peevcf581372017-04-07 13:53:10 +01001036 if (aeCancelTriggerNeeded) {
1037 settingsOverride.unlock(halRequest.settings);
1038 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001039 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001040 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001041 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
1042
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001043 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001044 if (hasInputBuf) {
1045 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
1046 mInflightBuffers.erase(key);
1047 }
1048 for (size_t i = 0; i < numOutputBufs; i++) {
1049 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1050 mInflightBuffers.erase(key);
1051 }
Emilian Peevcf581372017-04-07 13:53:10 +01001052 if (aeCancelTriggerNeeded) {
1053 mInflightAETriggerOverrides.erase(request.frameNumber);
1054 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001055 return Status::INTERNAL_ERROR;
1056 }
1057
1058 return Status::OK;
1059}
1060
1061Return<Status> CameraDeviceSession::flush() {
1062 Status status = initStatus();
1063 if (status == Status::OK) {
1064 // Flush is always supported on device 3.1 or later
1065 status_t ret = mDevice->ops->flush(mDevice);
1066 if (ret != OK) {
1067 status = Status::INTERNAL_ERROR;
1068 }
1069 }
1070 return status;
1071}
1072
1073Return<void> CameraDeviceSession::close() {
1074 Mutex::Autolock _l(mStateLock);
1075 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001076 {
1077 Mutex::Autolock _l(mInflightLock);
1078 if (!mInflightBuffers.empty()) {
1079 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
1080 __FUNCTION__, mInflightBuffers.size());
1081 }
Emilian Peevcf581372017-04-07 13:53:10 +01001082 if (!mInflightAETriggerOverrides.empty()) {
1083 ALOGE("%s: trying to close while there are still %zu inflight "
1084 "trigger overrides!", __FUNCTION__,
1085 mInflightAETriggerOverrides.size());
1086 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001087 if (!mInflightRawBoostPresent.empty()) {
1088 ALOGE("%s: trying to close while there are still %zu inflight "
1089 " RAW boost overrides!", __FUNCTION__,
1090 mInflightRawBoostPresent.size());
1091 }
Emilian Peevcf581372017-04-07 13:53:10 +01001092
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001093 }
1094
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001095 ATRACE_BEGIN("camera3->close");
1096 mDevice->common.close(&mDevice->common);
1097 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001098
1099 // free all imported buffers
1100 for(auto& pair : mCirculatingBuffers) {
1101 CirculatingBuffers& buffers = pair.second;
1102 for (auto& p2 : buffers) {
1103 sHandleImporter.freeBuffer(p2.second);
1104 }
1105 }
1106
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001107 mClosed = true;
1108 }
1109 return Void();
1110}
1111
1112/**
1113 * Static callback forwarding methods from HAL to instance
1114 */
1115void CameraDeviceSession::sProcessCaptureResult(
1116 const camera3_callback_ops *cb,
1117 const camera3_capture_result *hal_result) {
1118 CameraDeviceSession *d =
1119 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1120
1121 uint32_t frameNumber = hal_result->frame_number;
1122 bool hasInputBuf = (hal_result->input_buffer != nullptr);
1123 size_t numOutputBufs = hal_result->num_output_buffers;
1124 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001125 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001126 Mutex::Autolock _l(d->mInflightLock);
1127 if (hasInputBuf) {
1128 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1129 // validate if buffer is inflight
1130 auto key = std::make_pair(streamId, frameNumber);
1131 if (d->mInflightBuffers.count(key) != 1) {
1132 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
1133 __FUNCTION__, streamId, frameNumber);
1134 return;
1135 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001136 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001137
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001138 for (size_t i = 0; i < numOutputBufs; i++) {
1139 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1140 // validate if buffer is inflight
1141 auto key = std::make_pair(streamId, frameNumber);
1142 if (d->mInflightBuffers.count(key) != 1) {
1143 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
1144 __FUNCTION__, streamId, frameNumber);
1145 return;
1146 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001147 }
1148 }
1149 // We don't need to validate/import fences here since we will be passing them to camera service
1150 // within the scope of this function
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001151 CaptureResult result;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001152 result.frameNumber = frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -07001153 result.fmqResultSize = 0;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001154 result.partialResult = hal_result->partial_result;
1155 convertToHidl(hal_result->result, &result.result);
Emilian Peevcf581372017-04-07 13:53:10 +01001156 if (nullptr != hal_result->result) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001157 bool resultOverriden = false;
Emilian Peevcf581372017-04-07 13:53:10 +01001158 Mutex::Autolock _l(d->mInflightLock);
Emilian Peeva13ac992017-04-10 12:02:17 +01001159
1160 // Derive some new keys for backward compatibility
1161 if (d->mDerivePostRawSensKey) {
1162 camera_metadata_ro_entry entry;
1163 if (find_camera_metadata_ro_entry(hal_result->result,
1164 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, &entry) == 0) {
1165 d->mInflightRawBoostPresent[frameNumber] = true;
1166 } else {
1167 auto entry = d->mInflightRawBoostPresent.find(frameNumber);
1168 if (d->mInflightRawBoostPresent.end() == entry) {
1169 d->mInflightRawBoostPresent[frameNumber] = false;
1170 }
1171 }
1172
1173 if ((hal_result->partial_result == d->mNumPartialResults)) {
1174 if (!d->mInflightRawBoostPresent[frameNumber]) {
1175 if (!resultOverriden) {
1176 d->mOverridenResult.clear();
1177 d->mOverridenResult.append(hal_result->result);
1178 resultOverriden = true;
1179 }
1180 int32_t defaultBoost[1] = {100};
1181 d->mOverridenResult.update(
1182 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
1183 defaultBoost, 1);
1184 }
1185
1186 d->mInflightRawBoostPresent.erase(frameNumber);
1187 }
1188 }
1189
Emilian Peevcf581372017-04-07 13:53:10 +01001190 auto entry = d->mInflightAETriggerOverrides.find(frameNumber);
1191 if (d->mInflightAETriggerOverrides.end() != entry) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001192 if (!resultOverriden) {
1193 d->mOverridenResult.clear();
1194 d->mOverridenResult.append(hal_result->result);
1195 resultOverriden = true;
1196 }
Emilian Peevcf581372017-04-07 13:53:10 +01001197 d->overrideResultForPrecaptureCancelLocked(entry->second,
1198 &d->mOverridenResult);
Emilian Peevcf581372017-04-07 13:53:10 +01001199 if (hal_result->partial_result == d->mNumPartialResults) {
1200 d->mInflightAETriggerOverrides.erase(frameNumber);
1201 }
1202 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001203
1204 if (resultOverriden) {
1205 const camera_metadata_t *metaBuffer =
1206 d->mOverridenResult.getAndLock();
1207 convertToHidl(metaBuffer, &result.result);
1208 d->mOverridenResult.unlock(metaBuffer);
1209 }
Emilian Peevcf581372017-04-07 13:53:10 +01001210 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001211 if (hasInputBuf) {
1212 result.inputBuffer.streamId =
1213 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1214 result.inputBuffer.buffer = nullptr;
1215 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
1216 // skip acquire fence since it's no use to camera service
1217 if (hal_result->input_buffer->release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001218 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1219 handle->data[0] = hal_result->input_buffer->release_fence;
1220 result.inputBuffer.releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001221 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001222 result.inputBuffer.releaseFence = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001223 }
1224 } else {
1225 result.inputBuffer.streamId = -1;
1226 }
1227
1228 result.outputBuffers.resize(numOutputBufs);
1229 for (size_t i = 0; i < numOutputBufs; i++) {
1230 result.outputBuffers[i].streamId =
1231 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1232 result.outputBuffers[i].buffer = nullptr;
1233 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
1234 // skip acquire fence since it's of no use to camera service
1235 if (hal_result->output_buffers[i].release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001236 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1237 handle->data[0] = hal_result->output_buffers[i].release_fence;
1238 result.outputBuffers[i].releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001239 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001240 result.outputBuffers[i].releaseFence = nullptr;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001241 }
1242 }
1243
1244 // Free inflight record/fences.
1245 // Do this before call back to camera service because camera service might jump to
1246 // configure_streams right after the processCaptureResult call so we need to finish
1247 // updating inflight queues first
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001248 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001249 Mutex::Autolock _l(d->mInflightLock);
1250 if (hasInputBuf) {
1251 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1252 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001253 d->mInflightBuffers.erase(key);
1254 }
1255
1256 for (size_t i = 0; i < numOutputBufs; i++) {
1257 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1258 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001259 d->mInflightBuffers.erase(key);
1260 }
1261
1262 if (d->mInflightBuffers.empty()) {
1263 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001264 }
1265 }
1266
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001267 d->mResultBatcher.processCaptureResult(result);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001268}
1269
1270void CameraDeviceSession::sNotify(
1271 const camera3_callback_ops *cb,
1272 const camera3_notify_msg *msg) {
1273 CameraDeviceSession *d =
1274 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1275 NotifyMsg hidlMsg;
1276 convertToHidl(msg, &hidlMsg);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001277
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001278 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
1279 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001280 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
1281 ALOGE("%s: unknown stream ID %d reports an error!",
1282 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001283 return;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001284 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001285 }
Emilian Peevcf581372017-04-07 13:53:10 +01001286
1287 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
1288 switch (hidlMsg.msg.error.errorCode) {
1289 case ErrorCode::ERROR_DEVICE:
1290 case ErrorCode::ERROR_REQUEST:
1291 case ErrorCode::ERROR_RESULT: {
1292 Mutex::Autolock _l(d->mInflightLock);
1293 auto entry = d->mInflightAETriggerOverrides.find(
1294 hidlMsg.msg.error.frameNumber);
1295 if (d->mInflightAETriggerOverrides.end() != entry) {
1296 d->mInflightAETriggerOverrides.erase(
1297 hidlMsg.msg.error.frameNumber);
1298 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001299
1300 auto boostEntry = d->mInflightRawBoostPresent.find(
1301 hidlMsg.msg.error.frameNumber);
1302 if (d->mInflightRawBoostPresent.end() != boostEntry) {
1303 d->mInflightRawBoostPresent.erase(
1304 hidlMsg.msg.error.frameNumber);
1305 }
1306
Emilian Peevcf581372017-04-07 13:53:10 +01001307 }
1308 break;
1309 case ErrorCode::ERROR_BUFFER:
1310 default:
1311 break;
1312 }
1313
1314 }
1315
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001316 d->mResultBatcher.notify(hidlMsg);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001317}
1318
1319} // namespace implementation
1320} // namespace V3_2
1321} // namespace device
1322} // namespace camera
1323} // namespace hardware
1324} // namespace android