blob: ae275ae074c0d9c92e4354c3418bea91b78fde4c [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 "[email protected]"
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) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080052 mDeviceInfo = deviceInfo;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080053 camera_metadata_entry partialResultsCount =
54 mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
55 if (partialResultsCount.count > 0) {
Emilian Peevcf581372017-04-07 13:53:10 +010056 mNumPartialResults = partialResultsCount.data.i32[0];
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080057 }
Emilian Peevcf581372017-04-07 13:53:10 +010058 mResultBatcher.setNumPartialResults(mNumPartialResults);
59
60 camera_metadata_entry aeLockAvailableEntry = mDeviceInfo.find(
61 ANDROID_CONTROL_AE_LOCK_AVAILABLE);
62 if (aeLockAvailableEntry.count > 0) {
63 mIsAELockAvailable = (aeLockAvailableEntry.data.u8[0] ==
64 ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
65 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -080066
Emilian Peeva13ac992017-04-10 12:02:17 +010067 // Determine whether we need to derive sensitivity boost values for older devices.
68 // If post-RAW sensitivity boost range is listed, so should post-raw sensitivity control
69 // be listed (as the default value 100)
70 if (mDeviceInfo.exists(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE)) {
71 mDerivePostRawSensKey = true;
72 }
73
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070074 mInitFail = initialize();
75}
76
77bool CameraDeviceSession::initialize() {
78 /** Initialize device with callback functions */
79 ATRACE_BEGIN("camera3->initialize");
80 status_t res = mDevice->ops->initialize(mDevice, this);
81 ATRACE_END();
82
83 if (res != OK) {
84 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
85 __FUNCTION__, strerror(-res), res);
86 mDevice->common.close(&mDevice->common);
87 mClosed = true;
88 return true;
89 }
Yifan Hong1192e1d2017-04-11 14:45:00 -070090
91 mRequestMetadataQueue = std::make_unique<RequestMetadataQueue>(
92 CAMERA_REQUEST_METADATA_QUEUE_SIZE, false /* non blocking */);
93 if (!mRequestMetadataQueue->isValid()) {
Yifan Hong993e3d02017-04-12 16:31:23 -070094 ALOGE("%s: invalid request fmq", __FUNCTION__);
Yifan Hong1192e1d2017-04-11 14:45:00 -070095 return true;
96 }
Yifan Hong993e3d02017-04-12 16:31:23 -070097 mResultMetadataQueue = std::make_shared<RequestMetadataQueue>(
98 CAMERA_RESULT_METADATA_QUEUE_SIZE, false /* non blocking */);
99 if (!mResultMetadataQueue->isValid()) {
100 ALOGE("%s: invalid result fmq", __FUNCTION__);
101 return true;
102 }
103 mResultBatcher.setResultMetadataQueue(mResultMetadataQueue);
Yifan Hong1192e1d2017-04-11 14:45:00 -0700104
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700105 return false;
106}
107
108CameraDeviceSession::~CameraDeviceSession() {
109 if (!isClosed()) {
110 ALOGE("CameraDeviceSession deleted before close!");
111 close();
112 }
113}
114
115bool CameraDeviceSession::isClosed() {
116 Mutex::Autolock _l(mStateLock);
117 return mClosed;
118}
119
120Status CameraDeviceSession::initStatus() const {
121 Mutex::Autolock _l(mStateLock);
122 Status status = Status::OK;
123 if (mInitFail) {
124 status = Status::INTERNAL_ERROR;
125 } else if (mDisconnected) {
126 status = Status::CAMERA_DISCONNECTED;
127 } else if (mClosed) {
128 status = Status::INTERNAL_ERROR;
129 }
130 return status;
131}
132
133void CameraDeviceSession::disconnect() {
134 Mutex::Autolock _l(mStateLock);
135 mDisconnected = true;
136 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
137 if (!mClosed) {
138 mDevice->common.close(&mDevice->common);
139 mClosed = true;
140 }
141}
142
143void CameraDeviceSession::dumpState(const native_handle_t* fd) {
144 if (!isClosed()) {
145 mDevice->ops->dump(mDevice, fd->data[0]);
146 }
147}
148
Emilian Peevcf581372017-04-07 13:53:10 +0100149/**
150 * For devices <= CAMERA_DEVICE_API_VERSION_3_2, AE_PRECAPTURE_TRIGGER_CANCEL is not supported so
151 * we need to override AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE and AE_LOCK_OFF
152 * to AE_LOCK_ON to start cancelling AE precapture. If AE lock is not available, it still overrides
153 * AE_PRECAPTURE_TRIGGER_CANCEL to AE_PRECAPTURE_TRIGGER_IDLE but doesn't add AE_LOCK_ON to the
154 * request.
155 */
156bool CameraDeviceSession::handleAePrecaptureCancelRequestLocked(
157 const camera3_capture_request_t &halRequest,
158 ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/,
159 AETriggerCancelOverride *override /*out*/) {
160 if ((mDeviceVersion > CAMERA_DEVICE_API_VERSION_3_2) ||
161 (nullptr == halRequest.settings) || (nullptr == settings) ||
162 (0 == get_camera_metadata_entry_count(halRequest.settings))) {
163 return false;
164 }
165
166 settings->clear();
167 settings->append(halRequest.settings);
168 camera_metadata_entry_t aePrecaptureTrigger =
169 settings->find(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER);
170 if (aePrecaptureTrigger.count > 0 &&
171 aePrecaptureTrigger.data.u8[0] ==
172 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL) {
173 // Always override CANCEL to IDLE
174 uint8_t aePrecaptureTrigger =
175 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE;
176 settings->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
177 &aePrecaptureTrigger, 1);
178 *override = { false, ANDROID_CONTROL_AE_LOCK_OFF,
179 true, ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL };
180
181 if (mIsAELockAvailable == true) {
182 camera_metadata_entry_t aeLock = settings->find(
183 ANDROID_CONTROL_AE_LOCK);
184 if (aeLock.count == 0 || aeLock.data.u8[0] ==
185 ANDROID_CONTROL_AE_LOCK_OFF) {
186 uint8_t aeLock = ANDROID_CONTROL_AE_LOCK_ON;
187 settings->update(ANDROID_CONTROL_AE_LOCK, &aeLock, 1);
188 override->applyAeLock = true;
189 override->aeLock = ANDROID_CONTROL_AE_LOCK_OFF;
190 }
191 }
192
193 return true;
194 }
195
196 return false;
197}
198
199/**
200 * Override result metadata for cancelling AE precapture trigger applied in
201 * handleAePrecaptureCancelRequestLocked().
202 */
203void CameraDeviceSession::overrideResultForPrecaptureCancelLocked(
204 const AETriggerCancelOverride &aeTriggerCancelOverride,
205 ::android::hardware::camera::common::V1_0::helper::CameraMetadata *settings /*out*/) {
206 if (aeTriggerCancelOverride.applyAeLock) {
207 // Only devices <= v3.2 should have this override
208 assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
209 settings->update(ANDROID_CONTROL_AE_LOCK, &aeTriggerCancelOverride.aeLock, 1);
210 }
211
212 if (aeTriggerCancelOverride.applyAePrecaptureTrigger) {
213 // Only devices <= v3.2 should have this override
214 assert(mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_2);
215 settings->update(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
216 &aeTriggerCancelOverride.aePrecaptureTrigger, 1);
217 }
218}
219
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700220Status CameraDeviceSession::importRequest(
221 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800222 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700223 hidl_vec<int>& allFences) {
224 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800225 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700226 size_t numOutputBufs = request.outputBuffers.size();
227 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
228 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800229 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800230 hidl_vec<uint64_t> allBufIds;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700231 allBufs.resize(numBufs);
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800232 allBufIds.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800233 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700234 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800235 std::vector<int32_t> streamIds(numBufs);
236
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700237 for (size_t i = 0; i < numOutputBufs; i++) {
238 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800239 allBufIds[i] = request.outputBuffers[i].bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800240 allBufPtrs[i] = &allBufs[i];
241 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700242 }
243 if (hasInputBuf) {
244 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800245 allBufIds[numOutputBufs] = request.inputBuffer.bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800246 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
247 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700248 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800249
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700250 for (size_t i = 0; i < numBufs; i++) {
251 buffer_handle_t buf = allBufs[i];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800252 uint64_t bufId = allBufIds[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800253 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800254 if (cbs.count(bufId) == 0) {
255 if (buf == nullptr) {
256 ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
257 return Status::ILLEGAL_ARGUMENT;
258 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800259 // Register a newly seen buffer
260 buffer_handle_t importedBuf = buf;
261 sHandleImporter.importBuffer(importedBuf);
262 if (importedBuf == nullptr) {
263 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
264 return Status::INTERNAL_ERROR;
265 } else {
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800266 cbs[bufId] = importedBuf;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800267 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700268 }
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800269 allBufPtrs[i] = &cbs[bufId];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700270 }
271
272 // All buffers are imported. Now validate output buffer acquire fences
273 for (size_t i = 0; i < numOutputBufs; i++) {
274 if (!sHandleImporter.importFence(
275 request.outputBuffers[i].acquireFence, allFences[i])) {
276 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800277 cleanupInflightFences(allFences, i);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700278 return Status::INTERNAL_ERROR;
279 }
280 }
281
282 // Validate input buffer acquire fences
283 if (hasInputBuf) {
284 if (!sHandleImporter.importFence(
285 request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
286 ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800287 cleanupInflightFences(allFences, numOutputBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700288 return Status::INTERNAL_ERROR;
289 }
290 }
291 return Status::OK;
292}
293
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800294void CameraDeviceSession::cleanupInflightFences(
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700295 hidl_vec<int>& allFences, size_t numFences) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700296 for (size_t j = 0; j < numFences; j++) {
297 sHandleImporter.closeFence(allFences[j]);
298 }
299}
300
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800301CameraDeviceSession::ResultBatcher::ResultBatcher(
302 const sp<ICameraDeviceCallback>& callback) : mCallback(callback) {};
303
304bool CameraDeviceSession::ResultBatcher::InflightBatch::allDelivered() const {
305 if (!mShutterDelivered) return false;
306
307 if (mPartialResultProgress < mNumPartialResults) {
308 return false;
309 }
310
311 for (const auto& pair : mBatchBufs) {
312 if (!pair.second.mDelivered) {
313 return false;
314 }
315 }
316 return true;
317}
318
319void CameraDeviceSession::ResultBatcher::setNumPartialResults(uint32_t n) {
320 Mutex::Autolock _l(mLock);
321 mNumPartialResults = n;
322}
323
324void CameraDeviceSession::ResultBatcher::setBatchedStreams(
325 const std::vector<int>& streamsToBatch) {
326 Mutex::Autolock _l(mLock);
327 mStreamsToBatch = streamsToBatch;
328}
329
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700330void CameraDeviceSession::ResultBatcher::setResultMetadataQueue(
331 std::shared_ptr<ResultMetadataQueue> q) {
Yifan Hong993e3d02017-04-12 16:31:23 -0700332 Mutex::Autolock _l(mLock);
333 mResultMetadataQueue = q;
334}
335
Emilian Peevb75aa352018-01-17 11:00:54 +0000336void CameraDeviceSession::ResultBatcher::registerBatch(uint32_t frameNumber, uint32_t batchSize) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800337 auto batch = std::make_shared<InflightBatch>();
Emilian Peevb75aa352018-01-17 11:00:54 +0000338 batch->mFirstFrame = frameNumber;
339 batch->mBatchSize = batchSize;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800340 batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
341 batch->mNumPartialResults = mNumPartialResults;
342 for (int id : mStreamsToBatch) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700343 batch->mBatchBufs.emplace(id, batch->mBatchSize);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800344 }
345 Mutex::Autolock _l(mLock);
346 mInflightBatches.push_back(batch);
347}
348
349std::pair<int, std::shared_ptr<CameraDeviceSession::ResultBatcher::InflightBatch>>
350CameraDeviceSession::ResultBatcher::getBatch(
351 uint32_t frameNumber) {
352 Mutex::Autolock _l(mLock);
353 int numBatches = mInflightBatches.size();
354 if (numBatches == 0) {
355 return std::make_pair(NOT_BATCHED, nullptr);
356 }
357 uint32_t frameMin = mInflightBatches[0]->mFirstFrame;
358 uint32_t frameMax = mInflightBatches[numBatches - 1]->mLastFrame;
359 if (frameNumber < frameMin || frameNumber > frameMax) {
360 return std::make_pair(NOT_BATCHED, nullptr);
361 }
362 for (int i = 0; i < numBatches; i++) {
363 if (frameNumber >= mInflightBatches[i]->mFirstFrame &&
364 frameNumber <= mInflightBatches[i]->mLastFrame) {
365 return std::make_pair(i, mInflightBatches[i]);
366 }
367 }
368 return std::make_pair(NOT_BATCHED, nullptr);
369}
370
371void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
372 Mutex::Autolock _l(mLock);
373 if (mInflightBatches.size() > 0) {
374 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
375 bool shouldRemove = false;
376 {
377 Mutex::Autolock _l(batch->mLock);
378 if (batch->allDelivered()) {
379 batch->mRemoved = true;
380 shouldRemove = true;
381 }
382 }
383 if (shouldRemove) {
384 mInflightBatches.pop_front();
385 }
386 }
387}
388
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700389void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(
390 std::shared_ptr<InflightBatch> batch) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800391 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
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700421void CameraDeviceSession::ResultBatcher::moveStreamBuffer(StreamBuffer&& src, StreamBuffer& dst) {
422 // Only dealing with releaseFence here. Assume buffer/acquireFence are null
423 const native_handle_t* handle = src.releaseFence.getNativeHandle();
424 src.releaseFence = nullptr;
425 dst = src;
426 dst.releaseFence = handle;
427 if (handle != dst.releaseFence.getNativeHandle()) {
428 ALOGE("%s: native handle cloned!", __FUNCTION__);
429 }
430}
431
432void CameraDeviceSession::ResultBatcher::pushStreamBuffer(
433 StreamBuffer&& src, std::vector<StreamBuffer>& dst) {
434 // Only dealing with releaseFence here. Assume buffer/acquireFence are null
435 const native_handle_t* handle = src.releaseFence.getNativeHandle();
436 src.releaseFence = nullptr;
437 dst.push_back(src);
438 dst.back().releaseFence = handle;
439 if (handle != dst.back().releaseFence.getNativeHandle()) {
440 ALOGE("%s: native handle cloned!", __FUNCTION__);
441 }
442}
443
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700444void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
445 std::shared_ptr<InflightBatch> batch) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800446 sendBatchBuffersLocked(batch, mStreamsToBatch);
447}
448
449void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
450 std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
451 size_t batchSize = 0;
452 for (int streamId : streams) {
453 auto it = batch->mBatchBufs.find(streamId);
454 if (it != batch->mBatchBufs.end()) {
455 InflightBatch::BufferBatch& bb = it->second;
456 if (bb.mDelivered) {
457 continue;
458 }
459 if (bb.mBuffers.size() > batchSize) {
460 batchSize = bb.mBuffers.size();
461 }
462 } else {
463 ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
464 return;
465 }
466 }
467
468 if (batchSize == 0) {
469 ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
470 for (int streamId : streams) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700471 auto it = batch->mBatchBufs.find(streamId);
472 if (it == batch->mBatchBufs.end()) {
473 ALOGE("%s: cannot find stream %d in batched buffers!", __FUNCTION__, streamId);
474 return;
475 }
476 InflightBatch::BufferBatch& bb = it->second;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800477 bb.mDelivered = true;
478 }
479 return;
480 }
481
482 hidl_vec<CaptureResult> results;
483 results.resize(batchSize);
484 for (size_t i = 0; i < batchSize; i++) {
485 results[i].frameNumber = batch->mFirstFrame + i;
Yifan Hong993e3d02017-04-12 16:31:23 -0700486 results[i].fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800487 results[i].partialResult = 0; // 0 for buffer only results
488 results[i].inputBuffer.streamId = -1;
489 results[i].inputBuffer.bufferId = 0;
490 results[i].inputBuffer.buffer = nullptr;
491 std::vector<StreamBuffer> outBufs;
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700492 outBufs.reserve(streams.size());
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800493 for (int streamId : streams) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700494 auto it = batch->mBatchBufs.find(streamId);
495 if (it == batch->mBatchBufs.end()) {
496 ALOGE("%s: cannot find stream %d in batched buffers!", __FUNCTION__, streamId);
497 return;
498 }
499 InflightBatch::BufferBatch& bb = it->second;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800500 if (bb.mDelivered) {
501 continue;
502 }
503 if (i < bb.mBuffers.size()) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700504 pushStreamBuffer(std::move(bb.mBuffers[i]), outBufs);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800505 }
506 }
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700507 results[i].outputBuffers.resize(outBufs.size());
508 for (size_t j = 0; j < outBufs.size(); j++) {
509 moveStreamBuffer(std::move(outBufs[j]), results[i].outputBuffers[j]);
510 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800511 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700512 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */false);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800513 freeReleaseFences(results);
514 for (int streamId : streams) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700515 auto it = batch->mBatchBufs.find(streamId);
516 if (it == batch->mBatchBufs.end()) {
517 ALOGE("%s: cannot find stream %d in batched buffers!", __FUNCTION__, streamId);
518 return;
519 }
520 InflightBatch::BufferBatch& bb = it->second;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800521 bb.mDelivered = true;
522 bb.mBuffers.clear();
523 }
524}
525
526void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
527 std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
528 if (lastPartialResultIdx <= batch->mPartialResultProgress) {
529 // Result has been delivered. Return
530 ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
531 return;
532 }
533
534 std::vector<CaptureResult> results;
535 std::vector<uint32_t> toBeRemovedIdxes;
536 for (auto& pair : batch->mResultMds) {
537 uint32_t partialIdx = pair.first;
538 if (partialIdx > lastPartialResultIdx) {
539 continue;
540 }
541 toBeRemovedIdxes.push_back(partialIdx);
542 InflightBatch::MetadataBatch& mb = pair.second;
543 for (const auto& p : mb.mMds) {
544 CaptureResult result;
545 result.frameNumber = p.first;
546 result.result = std::move(p.second);
Yifan Hong993e3d02017-04-12 16:31:23 -0700547 result.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800548 result.inputBuffer.streamId = -1;
549 result.inputBuffer.bufferId = 0;
550 result.inputBuffer.buffer = nullptr;
551 result.partialResult = partialIdx;
552 results.push_back(std::move(result));
553 }
554 mb.mMds.clear();
555 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700556 hidl_vec<CaptureResult> hResults;
557 hResults.setToExternal(results.data(), results.size());
558 invokeProcessCaptureResultCallback(hResults, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800559 batch->mPartialResultProgress = lastPartialResultIdx;
560 for (uint32_t partialIdx : toBeRemovedIdxes) {
561 batch->mResultMds.erase(partialIdx);
562 }
563}
564
565void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
566 mCallback->notify({msg});
567 return;
568}
569
570void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
571 uint32_t frameNumber;
572 if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
573 frameNumber = msg.msg.shutter.frameNumber;
574 } else {
575 frameNumber = msg.msg.error.frameNumber;
576 }
577
578 auto pair = getBatch(frameNumber);
579 int batchIdx = pair.first;
580 if (batchIdx == NOT_BATCHED) {
581 notifySingleMsg(msg);
582 return;
583 }
584
585 // When error happened, stop batching for all batches earlier
586 if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
587 Mutex::Autolock _l(mLock);
588 for (int i = 0; i <= batchIdx; i++) {
589 // Send batched data up
590 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
591 {
592 Mutex::Autolock _l(batch->mLock);
593 sendBatchShutterCbsLocked(batch);
594 sendBatchBuffersLocked(batch);
595 sendBatchMetadataLocked(batch, mNumPartialResults);
596 if (!batch->allDelivered()) {
597 ALOGE("%s: error: some batch data not sent back to framework!",
598 __FUNCTION__);
599 }
600 batch->mRemoved = true;
601 }
602 mInflightBatches.pop_front();
603 }
604 // Send the error up
605 notifySingleMsg(msg);
606 return;
607 }
608 // Queue shutter callbacks for future delivery
609 std::shared_ptr<InflightBatch> batch = pair.second;
610 {
611 Mutex::Autolock _l(batch->mLock);
612 // Check if the batch is removed (mostly by notify error) before lock was acquired
613 if (batch->mRemoved) {
614 // Fall back to non-batch path
615 notifySingleMsg(msg);
616 return;
617 }
618
619 batch->mShutterMsgs.push_back(msg);
620 if (frameNumber == batch->mLastFrame) {
621 sendBatchShutterCbsLocked(batch);
622 }
623 } // end of batch lock scope
624
625 // see if the batch is complete
626 if (frameNumber == batch->mLastFrame) {
627 checkAndRemoveFirstBatch();
628 }
629}
630
Yifan Hong993e3d02017-04-12 16:31:23 -0700631void CameraDeviceSession::ResultBatcher::invokeProcessCaptureResultCallback(
632 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
633 if (mProcessCaptureResultLock.tryLock() != OK) {
Shuzhen Wang20786772017-05-25 10:34:13 -0700634 ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
Yifan Hong993e3d02017-04-12 16:31:23 -0700635 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
636 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
637 __FUNCTION__);
638 return;
639 }
640 }
641 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
642 for (CaptureResult &result : results) {
643 if (result.result.size() > 0) {
644 if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
645 result.fmqResultSize = result.result.size();
646 result.result.resize(0);
647 } else {
648 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
649 result.fmqResultSize = 0;
650 }
651 }
652 }
653 }
654 mCallback->processCaptureResult(results);
655 mProcessCaptureResultLock.unlock();
656}
657
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800658void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700659 hidl_vec<CaptureResult> results;
660 results.resize(1);
661 results[0] = std::move(result);
Yifan Hong993e3d02017-04-12 16:31:23 -0700662 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800663 freeReleaseFences(results);
664 return;
665}
666
667void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
668 auto pair = getBatch(result.frameNumber);
669 int batchIdx = pair.first;
670 if (batchIdx == NOT_BATCHED) {
671 processOneCaptureResult(result);
672 return;
673 }
674 std::shared_ptr<InflightBatch> batch = pair.second;
675 {
676 Mutex::Autolock _l(batch->mLock);
677 // Check if the batch is removed (mostly by notify error) before lock was acquired
678 if (batch->mRemoved) {
679 // Fall back to non-batch path
680 processOneCaptureResult(result);
681 return;
682 }
683
684 // queue metadata
685 if (result.result.size() != 0) {
686 // Save a copy of metadata
687 batch->mResultMds[result.partialResult].mMds.push_back(
688 std::make_pair(result.frameNumber, result.result));
689 }
690
691 // queue buffer
692 std::vector<int> filledStreams;
693 std::vector<StreamBuffer> nonBatchedBuffers;
694 for (auto& buffer : result.outputBuffers) {
695 auto it = batch->mBatchBufs.find(buffer.streamId);
696 if (it != batch->mBatchBufs.end()) {
697 InflightBatch::BufferBatch& bb = it->second;
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700698 pushStreamBuffer(std::move(buffer), bb.mBuffers);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800699 filledStreams.push_back(buffer.streamId);
700 } else {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700701 pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800702 }
703 }
704
705 // send non-batched buffers up
706 if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
707 CaptureResult nonBatchedResult;
708 nonBatchedResult.frameNumber = result.frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -0700709 nonBatchedResult.fmqResultSize = 0;
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700710 nonBatchedResult.outputBuffers.resize(nonBatchedBuffers.size());
711 for (size_t i = 0; i < nonBatchedBuffers.size(); i++) {
712 moveStreamBuffer(
713 std::move(nonBatchedBuffers[i]), nonBatchedResult.outputBuffers[i]);
714 }
715 moveStreamBuffer(std::move(result.inputBuffer), nonBatchedResult.inputBuffer);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800716 nonBatchedResult.partialResult = 0; // 0 for buffer only results
717 processOneCaptureResult(nonBatchedResult);
718 }
719
720 if (result.frameNumber == batch->mLastFrame) {
721 // Send data up
722 if (result.partialResult > 0) {
723 sendBatchMetadataLocked(batch, result.partialResult);
724 }
725 // send buffer up
726 if (filledStreams.size() > 0) {
727 sendBatchBuffersLocked(batch, filledStreams);
728 }
729 }
730 } // end of batch lock scope
731
732 // see if the batch is complete
733 if (result.frameNumber == batch->mLastFrame) {
734 checkAndRemoveFirstBatch();
735 }
736}
737
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700738// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
739Return<void> CameraDeviceSession::constructDefaultRequestSettings(
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700740 RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700741 CameraMetadata outMetadata;
Eino-Ville Talvala658d30d2018-01-18 12:55:07 -0800742 Status status = constructDefaultRequestSettingsRaw( (int) type, &outMetadata);
743 _hidl_cb(status, outMetadata);
744 return Void();
745}
746
747Status CameraDeviceSession::constructDefaultRequestSettingsRaw(int type, CameraMetadata *outMetadata) {
748 Status status = initStatus();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700749 const camera_metadata_t *rawRequest;
750 if (status == Status::OK) {
751 ATRACE_BEGIN("camera3->construct_default_request_settings");
752 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
753 ATRACE_END();
754 if (rawRequest == nullptr) {
755 ALOGI("%s: template %d is not supported on this camera device",
756 __FUNCTION__, type);
757 status = Status::ILLEGAL_ARGUMENT;
758 } else {
Emilian Peeva13ac992017-04-10 12:02:17 +0100759 mOverridenRequest.clear();
760 mOverridenRequest.append(rawRequest);
761 // Derive some new keys for backward compatibility
762 if (mDerivePostRawSensKey && !mOverridenRequest.exists(
763 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST)) {
764 int32_t defaultBoost[1] = {100};
765 mOverridenRequest.update(
766 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
767 defaultBoost, 1);
768 const camera_metadata_t *metaBuffer =
769 mOverridenRequest.getAndLock();
Eino-Ville Talvala658d30d2018-01-18 12:55:07 -0800770 convertToHidl(metaBuffer, outMetadata);
Emilian Peeva13ac992017-04-10 12:02:17 +0100771 mOverridenRequest.unlock(metaBuffer);
772 } else {
Eino-Ville Talvala658d30d2018-01-18 12:55:07 -0800773 convertToHidl(rawRequest, outMetadata);
Emilian Peeva13ac992017-04-10 12:02:17 +0100774 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700775 }
776 }
Eino-Ville Talvala658d30d2018-01-18 12:55:07 -0800777 return status;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700778}
779
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100780/**
781 * Map Android N dataspace definitions back to Android M definitions, for
782 * use with HALv3.3 or older.
783 *
784 * Only map where correspondences exist, and otherwise preserve the value.
785 */
786android_dataspace CameraDeviceSession::mapToLegacyDataspace(
787 android_dataspace dataSpace) const {
788 if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
789 switch (dataSpace) {
790 case HAL_DATASPACE_V0_SRGB_LINEAR:
791 return HAL_DATASPACE_SRGB_LINEAR;
792 case HAL_DATASPACE_V0_SRGB:
793 return HAL_DATASPACE_SRGB;
794 case HAL_DATASPACE_V0_JFIF:
795 return HAL_DATASPACE_JFIF;
796 case HAL_DATASPACE_V0_BT601_625:
797 return HAL_DATASPACE_BT601_625;
798 case HAL_DATASPACE_V0_BT601_525:
799 return HAL_DATASPACE_BT601_525;
800 case HAL_DATASPACE_V0_BT709:
801 return HAL_DATASPACE_BT709;
802 default:
803 return dataSpace;
804 }
805 }
806
807 return dataSpace;
808}
809
Emilian Peeve18057b2017-11-13 16:03:44 +0000810bool CameraDeviceSession::preProcessConfigurationLocked(
811 const StreamConfiguration& requestedConfiguration,
812 camera3_stream_configuration_t *stream_list /*out*/,
813 hidl_vec<camera3_stream_t*> *streams /*out*/) {
814
815 if ((stream_list == nullptr) || (streams == nullptr)) {
816 return false;
817 }
818
819 stream_list->operation_mode = (uint32_t) requestedConfiguration.operationMode;
820 stream_list->num_streams = requestedConfiguration.streams.size();
821 streams->resize(stream_list->num_streams);
822 stream_list->streams = streams->data();
823
824 for (uint32_t i = 0; i < stream_list->num_streams; i++) {
825 int id = requestedConfiguration.streams[i].id;
826
827 if (mStreamMap.count(id) == 0) {
828 Camera3Stream stream;
829 convertFromHidl(requestedConfiguration.streams[i], &stream);
830 mStreamMap[id] = stream;
831 mStreamMap[id].data_space = mapToLegacyDataspace(
832 mStreamMap[id].data_space);
833 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
834 } else {
835 // width/height/format must not change, but usage/rotation might need to change
836 if (mStreamMap[id].stream_type !=
837 (int) requestedConfiguration.streams[i].streamType ||
838 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
839 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
840 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
841 mStreamMap[id].data_space !=
842 mapToLegacyDataspace( static_cast<android_dataspace_t> (
843 requestedConfiguration.streams[i].dataSpace))) {
844 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
845 return false;
846 }
847 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
848 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
849 }
850 (*streams)[i] = &mStreamMap[id];
851 }
852
853 return true;
854}
855
856void CameraDeviceSession::postProcessConfigurationLocked(
857 const StreamConfiguration& requestedConfiguration) {
858 // delete unused streams, note we do this after adding new streams to ensure new stream
859 // will not have the same address as deleted stream, and HAL has a chance to reference
860 // the to be deleted stream in configure_streams call
861 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
862 int id = it->first;
863 bool found = false;
864 for (const auto& stream : requestedConfiguration.streams) {
865 if (id == stream.id) {
866 found = true;
867 break;
868 }
869 }
870 if (!found) {
871 // Unmap all buffers of deleted stream
872 // in case the configuration call succeeds and HAL
873 // is able to release the corresponding resources too.
874 cleanupBuffersLocked(id);
875 it = mStreamMap.erase(it);
876 } else {
877 ++it;
878 }
879 }
880
881 // Track video streams
882 mVideoStreamIds.clear();
883 for (const auto& stream : requestedConfiguration.streams) {
884 if (stream.streamType == StreamType::OUTPUT &&
885 stream.usage &
886 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
887 mVideoStreamIds.push_back(stream.id);
888 }
889 }
890 mResultBatcher.setBatchedStreams(mVideoStreamIds);
891}
892
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700893Return<void> CameraDeviceSession::configureStreams(
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700894 const StreamConfiguration& requestedConfiguration,
895 ICameraDeviceSession::configureStreams_cb _hidl_cb) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700896 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800897 HalStreamConfiguration outStreams;
898
899 // hold the inflight lock for entire configureStreams scope since there must not be any
900 // inflight request/results during stream configuration.
901 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700902 if (!mInflightBuffers.empty()) {
903 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
904 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800905 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
906 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700907 }
908
Emilian Peevcf581372017-04-07 13:53:10 +0100909 if (!mInflightAETriggerOverrides.empty()) {
910 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
911 " trigger overrides!", __FUNCTION__,
912 mInflightAETriggerOverrides.size());
913 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
914 return Void();
915 }
916
Emilian Peeva13ac992017-04-10 12:02:17 +0100917 if (!mInflightRawBoostPresent.empty()) {
918 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
919 " boost overrides!", __FUNCTION__,
920 mInflightRawBoostPresent.size());
921 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
922 return Void();
923 }
924
Emilian Peev98014ff2017-02-02 16:20:12 +0000925 if (status != Status::OK) {
926 _hidl_cb(status, outStreams);
927 return Void();
928 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800929
Emilian Peeve18057b2017-11-13 16:03:44 +0000930 camera3_stream_configuration_t stream_list{};
Emilian Peev98014ff2017-02-02 16:20:12 +0000931 hidl_vec<camera3_stream_t*> streams;
Emilian Peeve18057b2017-11-13 16:03:44 +0000932 if (!preProcessConfigurationLocked(requestedConfiguration, &stream_list, &streams)) {
933 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
934 return Void();
Emilian Peev98014ff2017-02-02 16:20:12 +0000935 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700936
Emilian Peev98014ff2017-02-02 16:20:12 +0000937 ATRACE_BEGIN("camera3->configure_streams");
938 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
939 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700940
Emilian Peev98014ff2017-02-02 16:20:12 +0000941 // In case Hal returns error most likely it was not able to release
942 // the corresponding resources of the deleted streams.
943 if (ret == OK) {
Emilian Peeve18057b2017-11-13 16:03:44 +0000944 postProcessConfigurationLocked(requestedConfiguration);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700945 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000946
947 if (ret == -EINVAL) {
948 status = Status::ILLEGAL_ARGUMENT;
949 } else if (ret != OK) {
950 status = Status::INTERNAL_ERROR;
951 } else {
952 convertToHidl(stream_list, &outStreams);
Yin-Chia Yehe9ab8222017-07-27 11:36:44 -0700953 mFirstRequest = true;
Emilian Peev98014ff2017-02-02 16:20:12 +0000954 }
955
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700956 _hidl_cb(status, outStreams);
957 return Void();
958}
959
Emilian Peev98014ff2017-02-02 16:20:12 +0000960// Needs to get called after acquiring 'mInflightLock'
961void CameraDeviceSession::cleanupBuffersLocked(int id) {
962 for (auto& pair : mCirculatingBuffers.at(id)) {
963 sHandleImporter.freeBuffer(pair.second);
964 }
965 mCirculatingBuffers[id].clear();
966 mCirculatingBuffers.erase(id);
967}
968
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700969void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
970 Mutex::Autolock _l(mInflightLock);
971 for (auto& cache : cachesToRemove) {
972 auto cbsIt = mCirculatingBuffers.find(cache.streamId);
973 if (cbsIt == mCirculatingBuffers.end()) {
974 // The stream could have been removed
975 continue;
976 }
977 CirculatingBuffers& cbs = cbsIt->second;
978 auto it = cbs.find(cache.bufferId);
979 if (it != cbs.end()) {
980 sHandleImporter.freeBuffer(it->second);
981 cbs.erase(it);
982 } else {
983 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
984 __FUNCTION__, cache.streamId, cache.bufferId);
985 }
986 }
987}
988
Yifan Hong1192e1d2017-04-11 14:45:00 -0700989Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700990 ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) {
Yifan Hong1192e1d2017-04-11 14:45:00 -0700991 _hidl_cb(*mRequestMetadataQueue->getDesc());
992 return Void();
993}
994
Yifan Hong993e3d02017-04-12 16:31:23 -0700995Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -0700996 ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) {
Yifan Hong993e3d02017-04-12 16:31:23 -0700997 _hidl_cb(*mResultMetadataQueue->getDesc());
998 return Void();
999}
1000
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001001Return<void> CameraDeviceSession::processCaptureRequest(
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -07001002 const hidl_vec<CaptureRequest>& requests,
1003 const hidl_vec<BufferCache>& cachesToRemove,
Eino-Ville Talvala50fe4302017-08-22 16:15:09 -07001004 ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) {
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -07001005 updateBufferCaches(cachesToRemove);
1006
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001007 uint32_t numRequestProcessed = 0;
1008 Status s = Status::OK;
1009 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
1010 s = processOneCaptureRequest(requests[i]);
1011 if (s != Status::OK) {
1012 break;
1013 }
1014 }
1015
1016 if (s == Status::OK && requests.size() > 1) {
Emilian Peevb75aa352018-01-17 11:00:54 +00001017 mResultBatcher.registerBatch(requests[0].frameNumber, requests.size());
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001018 }
1019
1020 _hidl_cb(s, numRequestProcessed);
1021 return Void();
1022}
1023
1024Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001025 Status status = initStatus();
1026 if (status != Status::OK) {
1027 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
1028 return status;
1029 }
1030
1031 camera3_capture_request_t halRequest;
1032 halRequest.frame_number = request.frameNumber;
Yifan Hong1192e1d2017-04-11 14:45:00 -07001033
1034 bool converted = true;
1035 CameraMetadata settingsFmq; // settings from FMQ
1036 if (request.fmqSettingsSize > 0) {
1037 // non-blocking read; client must write metadata before calling
1038 // processOneCaptureRequest
1039 settingsFmq.resize(request.fmqSettingsSize);
1040 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
1041 if (read) {
1042 converted = convertFromHidl(settingsFmq, &halRequest.settings);
1043 } else {
1044 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
1045 converted = false;
1046 }
1047 } else {
1048 converted = convertFromHidl(request.settings, &halRequest.settings);
1049 }
1050
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001051 if (!converted) {
1052 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
Yin-Chia Yehe9ab8222017-07-27 11:36:44 -07001053 return Status::ILLEGAL_ARGUMENT;
1054 }
1055
1056 if (mFirstRequest && halRequest.settings == nullptr) {
1057 ALOGE("%s: capture request settings must not be null for first request!",
1058 __FUNCTION__);
1059 return Status::ILLEGAL_ARGUMENT;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001060 }
1061
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001062 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001063 hidl_vec<int> allFences;
1064 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -08001065 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001066 size_t numOutputBufs = request.outputBuffers.size();
1067 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehe9ab8222017-07-27 11:36:44 -07001068
1069 if (numOutputBufs == 0) {
1070 ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
1071 return Status::ILLEGAL_ARGUMENT;
1072 }
1073
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001074 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001075 if (status != Status::OK) {
1076 return status;
1077 }
1078
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001079 hidl_vec<camera3_stream_buffer_t> outHalBufs;
1080 outHalBufs.resize(numOutputBufs);
Emilian Peevcf581372017-04-07 13:53:10 +01001081 bool aeCancelTriggerNeeded = false;
1082 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001083 {
1084 Mutex::Autolock _l(mInflightLock);
1085 if (hasInputBuf) {
1086 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
1087 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
1088 convertFromHidl(
1089 allBufPtrs[numOutputBufs], request.inputBuffer.status,
1090 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
1091 &bufCache);
1092 halRequest.input_buffer = &bufCache;
1093 } else {
1094 halRequest.input_buffer = nullptr;
1095 }
1096
1097 halRequest.num_output_buffers = numOutputBufs;
1098 for (size_t i = 0; i < numOutputBufs; i++) {
1099 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1100 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
1101 convertFromHidl(
1102 allBufPtrs[i], request.outputBuffers[i].status,
1103 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
1104 &bufCache);
1105 outHalBufs[i] = bufCache;
1106 }
1107 halRequest.output_buffers = outHalBufs.data();
Emilian Peevcf581372017-04-07 13:53:10 +01001108
1109 AETriggerCancelOverride triggerOverride;
1110 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
1111 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
1112 if (aeCancelTriggerNeeded) {
1113 mInflightAETriggerOverrides[halRequest.frame_number] =
1114 triggerOverride;
1115 halRequest.settings = settingsOverride.getAndLock();
1116 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001117 }
Emilian Peevb75aa352018-01-17 11:00:54 +00001118 halRequest.num_physcam_settings = 0;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001119
1120 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
1121 ATRACE_BEGIN("camera3->process_capture_request");
1122 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
1123 ATRACE_END();
Emilian Peevcf581372017-04-07 13:53:10 +01001124 if (aeCancelTriggerNeeded) {
1125 settingsOverride.unlock(halRequest.settings);
1126 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001127 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001128 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001129 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
1130
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001131 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001132 if (hasInputBuf) {
1133 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
1134 mInflightBuffers.erase(key);
1135 }
1136 for (size_t i = 0; i < numOutputBufs; i++) {
1137 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1138 mInflightBuffers.erase(key);
1139 }
Emilian Peevcf581372017-04-07 13:53:10 +01001140 if (aeCancelTriggerNeeded) {
1141 mInflightAETriggerOverrides.erase(request.frameNumber);
1142 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001143 return Status::INTERNAL_ERROR;
1144 }
1145
Yin-Chia Yehe9ab8222017-07-27 11:36:44 -07001146 mFirstRequest = false;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001147 return Status::OK;
1148}
1149
1150Return<Status> CameraDeviceSession::flush() {
1151 Status status = initStatus();
1152 if (status == Status::OK) {
1153 // Flush is always supported on device 3.1 or later
1154 status_t ret = mDevice->ops->flush(mDevice);
1155 if (ret != OK) {
1156 status = Status::INTERNAL_ERROR;
1157 }
1158 }
1159 return status;
1160}
1161
1162Return<void> CameraDeviceSession::close() {
1163 Mutex::Autolock _l(mStateLock);
1164 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001165 {
1166 Mutex::Autolock _l(mInflightLock);
1167 if (!mInflightBuffers.empty()) {
1168 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
1169 __FUNCTION__, mInflightBuffers.size());
1170 }
Emilian Peevcf581372017-04-07 13:53:10 +01001171 if (!mInflightAETriggerOverrides.empty()) {
1172 ALOGE("%s: trying to close while there are still %zu inflight "
1173 "trigger overrides!", __FUNCTION__,
1174 mInflightAETriggerOverrides.size());
1175 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001176 if (!mInflightRawBoostPresent.empty()) {
1177 ALOGE("%s: trying to close while there are still %zu inflight "
1178 " RAW boost overrides!", __FUNCTION__,
1179 mInflightRawBoostPresent.size());
1180 }
Emilian Peevcf581372017-04-07 13:53:10 +01001181
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001182 }
1183
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001184 ATRACE_BEGIN("camera3->close");
1185 mDevice->common.close(&mDevice->common);
1186 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001187
1188 // free all imported buffers
1189 for(auto& pair : mCirculatingBuffers) {
1190 CirculatingBuffers& buffers = pair.second;
1191 for (auto& p2 : buffers) {
1192 sHandleImporter.freeBuffer(p2.second);
1193 }
1194 }
1195
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001196 mClosed = true;
1197 }
1198 return Void();
1199}
1200
1201/**
1202 * Static callback forwarding methods from HAL to instance
1203 */
1204void CameraDeviceSession::sProcessCaptureResult(
1205 const camera3_callback_ops *cb,
1206 const camera3_capture_result *hal_result) {
1207 CameraDeviceSession *d =
1208 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1209
1210 uint32_t frameNumber = hal_result->frame_number;
1211 bool hasInputBuf = (hal_result->input_buffer != nullptr);
1212 size_t numOutputBufs = hal_result->num_output_buffers;
1213 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001214 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001215 Mutex::Autolock _l(d->mInflightLock);
1216 if (hasInputBuf) {
1217 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1218 // validate if buffer is inflight
1219 auto key = std::make_pair(streamId, frameNumber);
1220 if (d->mInflightBuffers.count(key) != 1) {
1221 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
1222 __FUNCTION__, streamId, frameNumber);
1223 return;
1224 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001225 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001226
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001227 for (size_t i = 0; i < numOutputBufs; i++) {
1228 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1229 // validate if buffer is inflight
1230 auto key = std::make_pair(streamId, frameNumber);
1231 if (d->mInflightBuffers.count(key) != 1) {
1232 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
1233 __FUNCTION__, streamId, frameNumber);
1234 return;
1235 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001236 }
1237 }
1238 // We don't need to validate/import fences here since we will be passing them to camera service
1239 // within the scope of this function
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001240 CaptureResult result;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001241 result.frameNumber = frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -07001242 result.fmqResultSize = 0;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001243 result.partialResult = hal_result->partial_result;
1244 convertToHidl(hal_result->result, &result.result);
Emilian Peevcf581372017-04-07 13:53:10 +01001245 if (nullptr != hal_result->result) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001246 bool resultOverriden = false;
Emilian Peevcf581372017-04-07 13:53:10 +01001247 Mutex::Autolock _l(d->mInflightLock);
Emilian Peeva13ac992017-04-10 12:02:17 +01001248
1249 // Derive some new keys for backward compatibility
1250 if (d->mDerivePostRawSensKey) {
1251 camera_metadata_ro_entry entry;
1252 if (find_camera_metadata_ro_entry(hal_result->result,
1253 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, &entry) == 0) {
1254 d->mInflightRawBoostPresent[frameNumber] = true;
1255 } else {
1256 auto entry = d->mInflightRawBoostPresent.find(frameNumber);
1257 if (d->mInflightRawBoostPresent.end() == entry) {
1258 d->mInflightRawBoostPresent[frameNumber] = false;
1259 }
1260 }
1261
1262 if ((hal_result->partial_result == d->mNumPartialResults)) {
1263 if (!d->mInflightRawBoostPresent[frameNumber]) {
1264 if (!resultOverriden) {
1265 d->mOverridenResult.clear();
1266 d->mOverridenResult.append(hal_result->result);
1267 resultOverriden = true;
1268 }
1269 int32_t defaultBoost[1] = {100};
1270 d->mOverridenResult.update(
1271 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
1272 defaultBoost, 1);
1273 }
1274
1275 d->mInflightRawBoostPresent.erase(frameNumber);
1276 }
1277 }
1278
Emilian Peevcf581372017-04-07 13:53:10 +01001279 auto entry = d->mInflightAETriggerOverrides.find(frameNumber);
1280 if (d->mInflightAETriggerOverrides.end() != entry) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001281 if (!resultOverriden) {
1282 d->mOverridenResult.clear();
1283 d->mOverridenResult.append(hal_result->result);
1284 resultOverriden = true;
1285 }
Emilian Peevcf581372017-04-07 13:53:10 +01001286 d->overrideResultForPrecaptureCancelLocked(entry->second,
1287 &d->mOverridenResult);
Emilian Peevcf581372017-04-07 13:53:10 +01001288 if (hal_result->partial_result == d->mNumPartialResults) {
1289 d->mInflightAETriggerOverrides.erase(frameNumber);
1290 }
1291 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001292
1293 if (resultOverriden) {
1294 const camera_metadata_t *metaBuffer =
1295 d->mOverridenResult.getAndLock();
1296 convertToHidl(metaBuffer, &result.result);
1297 d->mOverridenResult.unlock(metaBuffer);
1298 }
Emilian Peevcf581372017-04-07 13:53:10 +01001299 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001300 if (hasInputBuf) {
1301 result.inputBuffer.streamId =
1302 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1303 result.inputBuffer.buffer = nullptr;
1304 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
1305 // skip acquire fence since it's no use to camera service
1306 if (hal_result->input_buffer->release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001307 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1308 handle->data[0] = hal_result->input_buffer->release_fence;
1309 result.inputBuffer.releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001310 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001311 result.inputBuffer.releaseFence = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001312 }
1313 } else {
1314 result.inputBuffer.streamId = -1;
1315 }
1316
1317 result.outputBuffers.resize(numOutputBufs);
1318 for (size_t i = 0; i < numOutputBufs; i++) {
1319 result.outputBuffers[i].streamId =
1320 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1321 result.outputBuffers[i].buffer = nullptr;
1322 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
1323 // skip acquire fence since it's of no use to camera service
1324 if (hal_result->output_buffers[i].release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001325 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1326 handle->data[0] = hal_result->output_buffers[i].release_fence;
1327 result.outputBuffers[i].releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001328 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001329 result.outputBuffers[i].releaseFence = nullptr;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001330 }
1331 }
1332
1333 // Free inflight record/fences.
1334 // Do this before call back to camera service because camera service might jump to
1335 // configure_streams right after the processCaptureResult call so we need to finish
1336 // updating inflight queues first
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001337 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001338 Mutex::Autolock _l(d->mInflightLock);
1339 if (hasInputBuf) {
1340 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1341 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001342 d->mInflightBuffers.erase(key);
1343 }
1344
1345 for (size_t i = 0; i < numOutputBufs; i++) {
1346 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1347 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001348 d->mInflightBuffers.erase(key);
1349 }
1350
1351 if (d->mInflightBuffers.empty()) {
1352 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001353 }
1354 }
1355
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001356 d->mResultBatcher.processCaptureResult(result);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001357}
1358
1359void CameraDeviceSession::sNotify(
1360 const camera3_callback_ops *cb,
1361 const camera3_notify_msg *msg) {
1362 CameraDeviceSession *d =
1363 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1364 NotifyMsg hidlMsg;
1365 convertToHidl(msg, &hidlMsg);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001366
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001367 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
1368 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001369 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
1370 ALOGE("%s: unknown stream ID %d reports an error!",
1371 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001372 return;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001373 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001374 }
Emilian Peevcf581372017-04-07 13:53:10 +01001375
1376 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
1377 switch (hidlMsg.msg.error.errorCode) {
1378 case ErrorCode::ERROR_DEVICE:
1379 case ErrorCode::ERROR_REQUEST:
1380 case ErrorCode::ERROR_RESULT: {
1381 Mutex::Autolock _l(d->mInflightLock);
1382 auto entry = d->mInflightAETriggerOverrides.find(
1383 hidlMsg.msg.error.frameNumber);
1384 if (d->mInflightAETriggerOverrides.end() != entry) {
1385 d->mInflightAETriggerOverrides.erase(
1386 hidlMsg.msg.error.frameNumber);
1387 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001388
1389 auto boostEntry = d->mInflightRawBoostPresent.find(
1390 hidlMsg.msg.error.frameNumber);
1391 if (d->mInflightRawBoostPresent.end() != boostEntry) {
1392 d->mInflightRawBoostPresent.erase(
1393 hidlMsg.msg.error.frameNumber);
1394 }
1395
Emilian Peevcf581372017-04-07 13:53:10 +01001396 }
1397 break;
1398 case ErrorCode::ERROR_BUFFER:
1399 default:
1400 break;
1401 }
1402
1403 }
1404
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001405 d->mResultBatcher.notify(hidlMsg);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001406}
1407
1408} // namespace implementation
1409} // namespace V3_2
1410} // namespace device
1411} // namespace camera
1412} // namespace hardware
1413} // namespace android