blob: fcd134f45e1b8cedb10700505b7e07d176ecc8a5 [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) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700344 batch->mBatchBufs.emplace(id, batch->mBatchSize);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800345 }
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
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
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800444void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
445 sendBatchBuffersLocked(batch, mStreamsToBatch);
446}
447
448void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
449 std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
450 size_t batchSize = 0;
451 for (int streamId : streams) {
452 auto it = batch->mBatchBufs.find(streamId);
453 if (it != batch->mBatchBufs.end()) {
454 InflightBatch::BufferBatch& bb = it->second;
455 if (bb.mDelivered) {
456 continue;
457 }
458 if (bb.mBuffers.size() > batchSize) {
459 batchSize = bb.mBuffers.size();
460 }
461 } else {
462 ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
463 return;
464 }
465 }
466
467 if (batchSize == 0) {
468 ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
469 for (int streamId : streams) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700470 auto it = batch->mBatchBufs.find(streamId);
471 if (it == batch->mBatchBufs.end()) {
472 ALOGE("%s: cannot find stream %d in batched buffers!", __FUNCTION__, streamId);
473 return;
474 }
475 InflightBatch::BufferBatch& bb = it->second;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800476 bb.mDelivered = true;
477 }
478 return;
479 }
480
481 hidl_vec<CaptureResult> results;
482 results.resize(batchSize);
483 for (size_t i = 0; i < batchSize; i++) {
484 results[i].frameNumber = batch->mFirstFrame + i;
Yifan Hong993e3d02017-04-12 16:31:23 -0700485 results[i].fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800486 results[i].partialResult = 0; // 0 for buffer only results
487 results[i].inputBuffer.streamId = -1;
488 results[i].inputBuffer.bufferId = 0;
489 results[i].inputBuffer.buffer = nullptr;
490 std::vector<StreamBuffer> outBufs;
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700491 outBufs.reserve(streams.size());
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800492 for (int streamId : streams) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700493 auto it = batch->mBatchBufs.find(streamId);
494 if (it == batch->mBatchBufs.end()) {
495 ALOGE("%s: cannot find stream %d in batched buffers!", __FUNCTION__, streamId);
496 return;
497 }
498 InflightBatch::BufferBatch& bb = it->second;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800499 if (bb.mDelivered) {
500 continue;
501 }
502 if (i < bb.mBuffers.size()) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700503 pushStreamBuffer(std::move(bb.mBuffers[i]), outBufs);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800504 }
505 }
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700506 results[i].outputBuffers.resize(outBufs.size());
507 for (size_t j = 0; j < outBufs.size(); j++) {
508 moveStreamBuffer(std::move(outBufs[j]), results[i].outputBuffers[j]);
509 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800510 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700511 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */false);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800512 freeReleaseFences(results);
513 for (int streamId : streams) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700514 auto it = batch->mBatchBufs.find(streamId);
515 if (it == batch->mBatchBufs.end()) {
516 ALOGE("%s: cannot find stream %d in batched buffers!", __FUNCTION__, streamId);
517 return;
518 }
519 InflightBatch::BufferBatch& bb = it->second;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800520 bb.mDelivered = true;
521 bb.mBuffers.clear();
522 }
523}
524
525void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
526 std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
527 if (lastPartialResultIdx <= batch->mPartialResultProgress) {
528 // Result has been delivered. Return
529 ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
530 return;
531 }
532
533 std::vector<CaptureResult> results;
534 std::vector<uint32_t> toBeRemovedIdxes;
535 for (auto& pair : batch->mResultMds) {
536 uint32_t partialIdx = pair.first;
537 if (partialIdx > lastPartialResultIdx) {
538 continue;
539 }
540 toBeRemovedIdxes.push_back(partialIdx);
541 InflightBatch::MetadataBatch& mb = pair.second;
542 for (const auto& p : mb.mMds) {
543 CaptureResult result;
544 result.frameNumber = p.first;
545 result.result = std::move(p.second);
Yifan Hong993e3d02017-04-12 16:31:23 -0700546 result.fmqResultSize = 0;
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800547 result.inputBuffer.streamId = -1;
548 result.inputBuffer.bufferId = 0;
549 result.inputBuffer.buffer = nullptr;
550 result.partialResult = partialIdx;
551 results.push_back(std::move(result));
552 }
553 mb.mMds.clear();
554 }
Yifan Hong993e3d02017-04-12 16:31:23 -0700555 hidl_vec<CaptureResult> hResults;
556 hResults.setToExternal(results.data(), results.size());
557 invokeProcessCaptureResultCallback(hResults, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800558 batch->mPartialResultProgress = lastPartialResultIdx;
559 for (uint32_t partialIdx : toBeRemovedIdxes) {
560 batch->mResultMds.erase(partialIdx);
561 }
562}
563
564void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
565 mCallback->notify({msg});
566 return;
567}
568
569void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
570 uint32_t frameNumber;
571 if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
572 frameNumber = msg.msg.shutter.frameNumber;
573 } else {
574 frameNumber = msg.msg.error.frameNumber;
575 }
576
577 auto pair = getBatch(frameNumber);
578 int batchIdx = pair.first;
579 if (batchIdx == NOT_BATCHED) {
580 notifySingleMsg(msg);
581 return;
582 }
583
584 // When error happened, stop batching for all batches earlier
585 if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
586 Mutex::Autolock _l(mLock);
587 for (int i = 0; i <= batchIdx; i++) {
588 // Send batched data up
589 std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
590 {
591 Mutex::Autolock _l(batch->mLock);
592 sendBatchShutterCbsLocked(batch);
593 sendBatchBuffersLocked(batch);
594 sendBatchMetadataLocked(batch, mNumPartialResults);
595 if (!batch->allDelivered()) {
596 ALOGE("%s: error: some batch data not sent back to framework!",
597 __FUNCTION__);
598 }
599 batch->mRemoved = true;
600 }
601 mInflightBatches.pop_front();
602 }
603 // Send the error up
604 notifySingleMsg(msg);
605 return;
606 }
607 // Queue shutter callbacks for future delivery
608 std::shared_ptr<InflightBatch> batch = pair.second;
609 {
610 Mutex::Autolock _l(batch->mLock);
611 // Check if the batch is removed (mostly by notify error) before lock was acquired
612 if (batch->mRemoved) {
613 // Fall back to non-batch path
614 notifySingleMsg(msg);
615 return;
616 }
617
618 batch->mShutterMsgs.push_back(msg);
619 if (frameNumber == batch->mLastFrame) {
620 sendBatchShutterCbsLocked(batch);
621 }
622 } // end of batch lock scope
623
624 // see if the batch is complete
625 if (frameNumber == batch->mLastFrame) {
626 checkAndRemoveFirstBatch();
627 }
628}
629
Yifan Hong993e3d02017-04-12 16:31:23 -0700630void CameraDeviceSession::ResultBatcher::invokeProcessCaptureResultCallback(
631 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
632 if (mProcessCaptureResultLock.tryLock() != OK) {
Shuzhen Wang20786772017-05-25 10:34:13 -0700633 ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
Yifan Hong993e3d02017-04-12 16:31:23 -0700634 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
635 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
636 __FUNCTION__);
637 return;
638 }
639 }
640 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
641 for (CaptureResult &result : results) {
642 if (result.result.size() > 0) {
643 if (mResultMetadataQueue->write(result.result.data(), result.result.size())) {
644 result.fmqResultSize = result.result.size();
645 result.result.resize(0);
646 } else {
647 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
648 result.fmqResultSize = 0;
649 }
650 }
651 }
652 }
653 mCallback->processCaptureResult(results);
654 mProcessCaptureResultLock.unlock();
655}
656
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800657void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700658 hidl_vec<CaptureResult> results;
659 results.resize(1);
660 results[0] = std::move(result);
Yifan Hong993e3d02017-04-12 16:31:23 -0700661 invokeProcessCaptureResultCallback(results, /* tryWriteFmq */true);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800662 freeReleaseFences(results);
663 return;
664}
665
666void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
667 auto pair = getBatch(result.frameNumber);
668 int batchIdx = pair.first;
669 if (batchIdx == NOT_BATCHED) {
670 processOneCaptureResult(result);
671 return;
672 }
673 std::shared_ptr<InflightBatch> batch = pair.second;
674 {
675 Mutex::Autolock _l(batch->mLock);
676 // Check if the batch is removed (mostly by notify error) before lock was acquired
677 if (batch->mRemoved) {
678 // Fall back to non-batch path
679 processOneCaptureResult(result);
680 return;
681 }
682
683 // queue metadata
684 if (result.result.size() != 0) {
685 // Save a copy of metadata
686 batch->mResultMds[result.partialResult].mMds.push_back(
687 std::make_pair(result.frameNumber, result.result));
688 }
689
690 // queue buffer
691 std::vector<int> filledStreams;
692 std::vector<StreamBuffer> nonBatchedBuffers;
693 for (auto& buffer : result.outputBuffers) {
694 auto it = batch->mBatchBufs.find(buffer.streamId);
695 if (it != batch->mBatchBufs.end()) {
696 InflightBatch::BufferBatch& bb = it->second;
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700697 pushStreamBuffer(std::move(buffer), bb.mBuffers);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800698 filledStreams.push_back(buffer.streamId);
699 } else {
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700700 pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800701 }
702 }
703
704 // send non-batched buffers up
705 if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
706 CaptureResult nonBatchedResult;
707 nonBatchedResult.frameNumber = result.frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -0700708 nonBatchedResult.fmqResultSize = 0;
Yin-Chia Yehaa699312017-05-26 14:01:32 -0700709 nonBatchedResult.outputBuffers.resize(nonBatchedBuffers.size());
710 for (size_t i = 0; i < nonBatchedBuffers.size(); i++) {
711 moveStreamBuffer(
712 std::move(nonBatchedBuffers[i]), nonBatchedResult.outputBuffers[i]);
713 }
714 moveStreamBuffer(std::move(result.inputBuffer), nonBatchedResult.inputBuffer);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800715 nonBatchedResult.partialResult = 0; // 0 for buffer only results
716 processOneCaptureResult(nonBatchedResult);
717 }
718
719 if (result.frameNumber == batch->mLastFrame) {
720 // Send data up
721 if (result.partialResult > 0) {
722 sendBatchMetadataLocked(batch, result.partialResult);
723 }
724 // send buffer up
725 if (filledStreams.size() > 0) {
726 sendBatchBuffersLocked(batch, filledStreams);
727 }
728 }
729 } // end of batch lock scope
730
731 // see if the batch is complete
732 if (result.frameNumber == batch->mLastFrame) {
733 checkAndRemoveFirstBatch();
734 }
735}
736
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700737// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
738Return<void> CameraDeviceSession::constructDefaultRequestSettings(
739 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
740 Status status = initStatus();
741 CameraMetadata outMetadata;
742 const camera_metadata_t *rawRequest;
743 if (status == Status::OK) {
744 ATRACE_BEGIN("camera3->construct_default_request_settings");
745 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
746 ATRACE_END();
747 if (rawRequest == nullptr) {
748 ALOGI("%s: template %d is not supported on this camera device",
749 __FUNCTION__, type);
750 status = Status::ILLEGAL_ARGUMENT;
751 } else {
Emilian Peeva13ac992017-04-10 12:02:17 +0100752 mOverridenRequest.clear();
753 mOverridenRequest.append(rawRequest);
754 // Derive some new keys for backward compatibility
755 if (mDerivePostRawSensKey && !mOverridenRequest.exists(
756 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST)) {
757 int32_t defaultBoost[1] = {100};
758 mOverridenRequest.update(
759 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
760 defaultBoost, 1);
761 const camera_metadata_t *metaBuffer =
762 mOverridenRequest.getAndLock();
763 convertToHidl(metaBuffer, &outMetadata);
764 mOverridenRequest.unlock(metaBuffer);
765 } else {
766 convertToHidl(rawRequest, &outMetadata);
767 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700768 }
769 }
770 _hidl_cb(status, outMetadata);
771 return Void();
772}
773
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100774/**
775 * Map Android N dataspace definitions back to Android M definitions, for
776 * use with HALv3.3 or older.
777 *
778 * Only map where correspondences exist, and otherwise preserve the value.
779 */
780android_dataspace CameraDeviceSession::mapToLegacyDataspace(
781 android_dataspace dataSpace) const {
782 if (mDeviceVersion <= CAMERA_DEVICE_API_VERSION_3_3) {
783 switch (dataSpace) {
784 case HAL_DATASPACE_V0_SRGB_LINEAR:
785 return HAL_DATASPACE_SRGB_LINEAR;
786 case HAL_DATASPACE_V0_SRGB:
787 return HAL_DATASPACE_SRGB;
788 case HAL_DATASPACE_V0_JFIF:
789 return HAL_DATASPACE_JFIF;
790 case HAL_DATASPACE_V0_BT601_625:
791 return HAL_DATASPACE_BT601_625;
792 case HAL_DATASPACE_V0_BT601_525:
793 return HAL_DATASPACE_BT601_525;
794 case HAL_DATASPACE_V0_BT709:
795 return HAL_DATASPACE_BT709;
796 default:
797 return dataSpace;
798 }
799 }
800
801 return dataSpace;
802}
803
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700804Return<void> CameraDeviceSession::configureStreams(
805 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
806 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800807 HalStreamConfiguration outStreams;
808
809 // hold the inflight lock for entire configureStreams scope since there must not be any
810 // inflight request/results during stream configuration.
811 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700812 if (!mInflightBuffers.empty()) {
813 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
814 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800815 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
816 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700817 }
818
Emilian Peevcf581372017-04-07 13:53:10 +0100819 if (!mInflightAETriggerOverrides.empty()) {
820 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
821 " trigger overrides!", __FUNCTION__,
822 mInflightAETriggerOverrides.size());
823 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
824 return Void();
825 }
826
Emilian Peeva13ac992017-04-10 12:02:17 +0100827 if (!mInflightRawBoostPresent.empty()) {
828 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
829 " boost overrides!", __FUNCTION__,
830 mInflightRawBoostPresent.size());
831 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
832 return Void();
833 }
834
Emilian Peev98014ff2017-02-02 16:20:12 +0000835 if (status != Status::OK) {
836 _hidl_cb(status, outStreams);
837 return Void();
838 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800839
Emilian Peev98014ff2017-02-02 16:20:12 +0000840 camera3_stream_configuration_t stream_list;
841 hidl_vec<camera3_stream_t*> streams;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800842
Emilian Peev98014ff2017-02-02 16:20:12 +0000843 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
844 stream_list.num_streams = requestedConfiguration.streams.size();
845 streams.resize(stream_list.num_streams);
846 stream_list.streams = streams.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700847
Emilian Peev98014ff2017-02-02 16:20:12 +0000848 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
849 int id = requestedConfiguration.streams[i].id;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700850
Emilian Peev98014ff2017-02-02 16:20:12 +0000851 if (mStreamMap.count(id) == 0) {
852 Camera3Stream stream;
853 convertFromHidl(requestedConfiguration.streams[i], &stream);
854 mStreamMap[id] = stream;
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100855 mStreamMap[id].data_space = mapToLegacyDataspace(
856 mStreamMap[id].data_space);
Emilian Peev98014ff2017-02-02 16:20:12 +0000857 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
858 } else {
859 // width/height/format must not change, but usage/rotation might need to change
860 if (mStreamMap[id].stream_type !=
861 (int) requestedConfiguration.streams[i].streamType ||
862 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
863 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
864 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
Emilian Peev7d52a6f2017-04-07 09:53:48 +0100865 mStreamMap[id].data_space !=
866 mapToLegacyDataspace( static_cast<android_dataspace_t> (
867 requestedConfiguration.streams[i].dataSpace))) {
Emilian Peev98014ff2017-02-02 16:20:12 +0000868 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
869 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
870 return Void();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800871 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000872 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
Yin-Chia Yehc25c54f2017-04-04 13:00:35 -0700873 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700874 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000875 streams[i] = &mStreamMap[id];
876 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700877
Emilian Peev98014ff2017-02-02 16:20:12 +0000878 ATRACE_BEGIN("camera3->configure_streams");
879 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
880 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700881
Emilian Peev98014ff2017-02-02 16:20:12 +0000882 // In case Hal returns error most likely it was not able to release
883 // the corresponding resources of the deleted streams.
884 if (ret == OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800885 // delete unused streams, note we do this after adding new streams to ensure new stream
886 // will not have the same address as deleted stream, and HAL has a chance to reference
887 // the to be deleted stream in configure_streams call
888 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
889 int id = it->first;
890 bool found = false;
891 for (const auto& stream : requestedConfiguration.streams) {
892 if (id == stream.id) {
893 found = true;
894 break;
895 }
896 }
897 if (!found) {
898 // Unmap all buffers of deleted stream
Emilian Peev98014ff2017-02-02 16:20:12 +0000899 // in case the configuration call succeeds and HAL
900 // is able to release the corresponding resources too.
901 cleanupBuffersLocked(id);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800902 it = mStreamMap.erase(it);
903 } else {
904 ++it;
905 }
906 }
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800907
908 // Track video streams
909 mVideoStreamIds.clear();
910 for (const auto& stream : requestedConfiguration.streams) {
911 if (stream.streamType == StreamType::OUTPUT &&
Chia-I Wu79d13ff2017-03-31 12:48:11 -0700912 stream.usage &
913 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800914 mVideoStreamIds.push_back(stream.id);
915 }
916 }
917 mResultBatcher.setBatchedStreams(mVideoStreamIds);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700918 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000919
920 if (ret == -EINVAL) {
921 status = Status::ILLEGAL_ARGUMENT;
922 } else if (ret != OK) {
923 status = Status::INTERNAL_ERROR;
924 } else {
925 convertToHidl(stream_list, &outStreams);
Yin-Chia Yehfafbc472017-07-26 16:53:20 -0700926 mFirstRequest = true;
Emilian Peev98014ff2017-02-02 16:20:12 +0000927 }
928
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700929 _hidl_cb(status, outStreams);
930 return Void();
931}
932
Emilian Peev98014ff2017-02-02 16:20:12 +0000933// Needs to get called after acquiring 'mInflightLock'
934void CameraDeviceSession::cleanupBuffersLocked(int id) {
935 for (auto& pair : mCirculatingBuffers.at(id)) {
936 sHandleImporter.freeBuffer(pair.second);
937 }
938 mCirculatingBuffers[id].clear();
939 mCirculatingBuffers.erase(id);
940}
941
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700942void CameraDeviceSession::updateBufferCaches(const hidl_vec<BufferCache>& cachesToRemove) {
943 Mutex::Autolock _l(mInflightLock);
944 for (auto& cache : cachesToRemove) {
945 auto cbsIt = mCirculatingBuffers.find(cache.streamId);
946 if (cbsIt == mCirculatingBuffers.end()) {
947 // The stream could have been removed
948 continue;
949 }
950 CirculatingBuffers& cbs = cbsIt->second;
951 auto it = cbs.find(cache.bufferId);
952 if (it != cbs.end()) {
953 sHandleImporter.freeBuffer(it->second);
954 cbs.erase(it);
955 } else {
956 ALOGE("%s: stream %d buffer %" PRIu64 " is not cached",
957 __FUNCTION__, cache.streamId, cache.bufferId);
958 }
959 }
960}
961
Yifan Hong1192e1d2017-04-11 14:45:00 -0700962Return<void> CameraDeviceSession::getCaptureRequestMetadataQueue(
963 getCaptureRequestMetadataQueue_cb _hidl_cb) {
964 _hidl_cb(*mRequestMetadataQueue->getDesc());
965 return Void();
966}
967
Yifan Hong993e3d02017-04-12 16:31:23 -0700968Return<void> CameraDeviceSession::getCaptureResultMetadataQueue(
969 getCaptureResultMetadataQueue_cb _hidl_cb) {
970 _hidl_cb(*mResultMetadataQueue->getDesc());
971 return Void();
972}
973
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800974Return<void> CameraDeviceSession::processCaptureRequest(
Yin-Chia Yeh28eebbf2017-03-30 15:06:20 -0700975 const hidl_vec<CaptureRequest>& requests,
976 const hidl_vec<BufferCache>& cachesToRemove,
977 processCaptureRequest_cb _hidl_cb) {
978 updateBufferCaches(cachesToRemove);
979
Yin-Chia Yehbed3a942017-03-06 14:14:17 -0800980 uint32_t numRequestProcessed = 0;
981 Status s = Status::OK;
982 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
983 s = processOneCaptureRequest(requests[i]);
984 if (s != Status::OK) {
985 break;
986 }
987 }
988
989 if (s == Status::OK && requests.size() > 1) {
990 mResultBatcher.registerBatch(requests);
991 }
992
993 _hidl_cb(s, numRequestProcessed);
994 return Void();
995}
996
997Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700998 Status status = initStatus();
999 if (status != Status::OK) {
1000 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
1001 return status;
1002 }
1003
1004 camera3_capture_request_t halRequest;
1005 halRequest.frame_number = request.frameNumber;
Yifan Hong1192e1d2017-04-11 14:45:00 -07001006
1007 bool converted = true;
1008 CameraMetadata settingsFmq; // settings from FMQ
1009 if (request.fmqSettingsSize > 0) {
1010 // non-blocking read; client must write metadata before calling
1011 // processOneCaptureRequest
1012 settingsFmq.resize(request.fmqSettingsSize);
1013 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
1014 if (read) {
1015 converted = convertFromHidl(settingsFmq, &halRequest.settings);
1016 } else {
1017 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
1018 converted = false;
1019 }
1020 } else {
1021 converted = convertFromHidl(request.settings, &halRequest.settings);
1022 }
1023
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001024 if (!converted) {
1025 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
Yin-Chia Yehfafbc472017-07-26 16:53:20 -07001026 return Status::ILLEGAL_ARGUMENT;
1027 }
1028
1029 if (mFirstRequest && halRequest.settings == nullptr) {
1030 ALOGE("%s: capture request settings must not be null for first request!",
1031 __FUNCTION__);
1032 return Status::ILLEGAL_ARGUMENT;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001033 }
1034
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001035 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001036 hidl_vec<int> allFences;
1037 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -08001038 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001039 size_t numOutputBufs = request.outputBuffers.size();
1040 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehfafbc472017-07-26 16:53:20 -07001041
1042 if (numOutputBufs == 0) {
1043 ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
1044 return Status::ILLEGAL_ARGUMENT;
1045 }
1046
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001047 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001048 if (status != Status::OK) {
1049 return status;
1050 }
1051
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001052 hidl_vec<camera3_stream_buffer_t> outHalBufs;
1053 outHalBufs.resize(numOutputBufs);
Emilian Peevcf581372017-04-07 13:53:10 +01001054 bool aeCancelTriggerNeeded = false;
1055 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001056 {
1057 Mutex::Autolock _l(mInflightLock);
1058 if (hasInputBuf) {
1059 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
1060 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
1061 convertFromHidl(
1062 allBufPtrs[numOutputBufs], request.inputBuffer.status,
1063 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
1064 &bufCache);
1065 halRequest.input_buffer = &bufCache;
1066 } else {
1067 halRequest.input_buffer = nullptr;
1068 }
1069
1070 halRequest.num_output_buffers = numOutputBufs;
1071 for (size_t i = 0; i < numOutputBufs; i++) {
1072 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1073 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
1074 convertFromHidl(
1075 allBufPtrs[i], request.outputBuffers[i].status,
1076 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
1077 &bufCache);
1078 outHalBufs[i] = bufCache;
1079 }
1080 halRequest.output_buffers = outHalBufs.data();
Emilian Peevcf581372017-04-07 13:53:10 +01001081
1082 AETriggerCancelOverride triggerOverride;
1083 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
1084 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
1085 if (aeCancelTriggerNeeded) {
1086 mInflightAETriggerOverrides[halRequest.frame_number] =
1087 triggerOverride;
1088 halRequest.settings = settingsOverride.getAndLock();
1089 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001090 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001091
1092 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
1093 ATRACE_BEGIN("camera3->process_capture_request");
1094 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
1095 ATRACE_END();
Emilian Peevcf581372017-04-07 13:53:10 +01001096 if (aeCancelTriggerNeeded) {
1097 settingsOverride.unlock(halRequest.settings);
1098 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001099 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001100 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001101 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
1102
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001103 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001104 if (hasInputBuf) {
1105 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
1106 mInflightBuffers.erase(key);
1107 }
1108 for (size_t i = 0; i < numOutputBufs; i++) {
1109 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
1110 mInflightBuffers.erase(key);
1111 }
Emilian Peevcf581372017-04-07 13:53:10 +01001112 if (aeCancelTriggerNeeded) {
1113 mInflightAETriggerOverrides.erase(request.frameNumber);
1114 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001115 return Status::INTERNAL_ERROR;
1116 }
1117
Yin-Chia Yehfafbc472017-07-26 16:53:20 -07001118 mFirstRequest = false;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001119 return Status::OK;
1120}
1121
1122Return<Status> CameraDeviceSession::flush() {
1123 Status status = initStatus();
1124 if (status == Status::OK) {
1125 // Flush is always supported on device 3.1 or later
1126 status_t ret = mDevice->ops->flush(mDevice);
1127 if (ret != OK) {
1128 status = Status::INTERNAL_ERROR;
1129 }
1130 }
1131 return status;
1132}
1133
1134Return<void> CameraDeviceSession::close() {
1135 Mutex::Autolock _l(mStateLock);
1136 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001137 {
1138 Mutex::Autolock _l(mInflightLock);
1139 if (!mInflightBuffers.empty()) {
1140 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
1141 __FUNCTION__, mInflightBuffers.size());
1142 }
Emilian Peevcf581372017-04-07 13:53:10 +01001143 if (!mInflightAETriggerOverrides.empty()) {
1144 ALOGE("%s: trying to close while there are still %zu inflight "
1145 "trigger overrides!", __FUNCTION__,
1146 mInflightAETriggerOverrides.size());
1147 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001148 if (!mInflightRawBoostPresent.empty()) {
1149 ALOGE("%s: trying to close while there are still %zu inflight "
1150 " RAW boost overrides!", __FUNCTION__,
1151 mInflightRawBoostPresent.size());
1152 }
Emilian Peevcf581372017-04-07 13:53:10 +01001153
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001154 }
1155
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001156 ATRACE_BEGIN("camera3->close");
1157 mDevice->common.close(&mDevice->common);
1158 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001159
1160 // free all imported buffers
1161 for(auto& pair : mCirculatingBuffers) {
1162 CirculatingBuffers& buffers = pair.second;
1163 for (auto& p2 : buffers) {
1164 sHandleImporter.freeBuffer(p2.second);
1165 }
1166 }
1167
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001168 mClosed = true;
1169 }
1170 return Void();
1171}
1172
1173/**
1174 * Static callback forwarding methods from HAL to instance
1175 */
1176void CameraDeviceSession::sProcessCaptureResult(
1177 const camera3_callback_ops *cb,
1178 const camera3_capture_result *hal_result) {
1179 CameraDeviceSession *d =
1180 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1181
1182 uint32_t frameNumber = hal_result->frame_number;
1183 bool hasInputBuf = (hal_result->input_buffer != nullptr);
1184 size_t numOutputBufs = hal_result->num_output_buffers;
1185 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001186 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001187 Mutex::Autolock _l(d->mInflightLock);
1188 if (hasInputBuf) {
1189 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1190 // validate if buffer is inflight
1191 auto key = std::make_pair(streamId, frameNumber);
1192 if (d->mInflightBuffers.count(key) != 1) {
1193 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
1194 __FUNCTION__, streamId, frameNumber);
1195 return;
1196 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001197 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001198
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001199 for (size_t i = 0; i < numOutputBufs; i++) {
1200 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1201 // validate if buffer is inflight
1202 auto key = std::make_pair(streamId, frameNumber);
1203 if (d->mInflightBuffers.count(key) != 1) {
1204 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
1205 __FUNCTION__, streamId, frameNumber);
1206 return;
1207 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001208 }
1209 }
1210 // We don't need to validate/import fences here since we will be passing them to camera service
1211 // within the scope of this function
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001212 CaptureResult result;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001213 result.frameNumber = frameNumber;
Yifan Hong993e3d02017-04-12 16:31:23 -07001214 result.fmqResultSize = 0;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001215 result.partialResult = hal_result->partial_result;
1216 convertToHidl(hal_result->result, &result.result);
Emilian Peevcf581372017-04-07 13:53:10 +01001217 if (nullptr != hal_result->result) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001218 bool resultOverriden = false;
Emilian Peevcf581372017-04-07 13:53:10 +01001219 Mutex::Autolock _l(d->mInflightLock);
Emilian Peeva13ac992017-04-10 12:02:17 +01001220
1221 // Derive some new keys for backward compatibility
1222 if (d->mDerivePostRawSensKey) {
1223 camera_metadata_ro_entry entry;
1224 if (find_camera_metadata_ro_entry(hal_result->result,
1225 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, &entry) == 0) {
1226 d->mInflightRawBoostPresent[frameNumber] = true;
1227 } else {
1228 auto entry = d->mInflightRawBoostPresent.find(frameNumber);
1229 if (d->mInflightRawBoostPresent.end() == entry) {
1230 d->mInflightRawBoostPresent[frameNumber] = false;
1231 }
1232 }
1233
1234 if ((hal_result->partial_result == d->mNumPartialResults)) {
1235 if (!d->mInflightRawBoostPresent[frameNumber]) {
1236 if (!resultOverriden) {
1237 d->mOverridenResult.clear();
1238 d->mOverridenResult.append(hal_result->result);
1239 resultOverriden = true;
1240 }
1241 int32_t defaultBoost[1] = {100};
1242 d->mOverridenResult.update(
1243 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
1244 defaultBoost, 1);
1245 }
1246
1247 d->mInflightRawBoostPresent.erase(frameNumber);
1248 }
1249 }
1250
Emilian Peevcf581372017-04-07 13:53:10 +01001251 auto entry = d->mInflightAETriggerOverrides.find(frameNumber);
1252 if (d->mInflightAETriggerOverrides.end() != entry) {
Emilian Peeva13ac992017-04-10 12:02:17 +01001253 if (!resultOverriden) {
1254 d->mOverridenResult.clear();
1255 d->mOverridenResult.append(hal_result->result);
1256 resultOverriden = true;
1257 }
Emilian Peevcf581372017-04-07 13:53:10 +01001258 d->overrideResultForPrecaptureCancelLocked(entry->second,
1259 &d->mOverridenResult);
Emilian Peevcf581372017-04-07 13:53:10 +01001260 if (hal_result->partial_result == d->mNumPartialResults) {
1261 d->mInflightAETriggerOverrides.erase(frameNumber);
1262 }
1263 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001264
1265 if (resultOverriden) {
1266 const camera_metadata_t *metaBuffer =
1267 d->mOverridenResult.getAndLock();
1268 convertToHidl(metaBuffer, &result.result);
1269 d->mOverridenResult.unlock(metaBuffer);
1270 }
Emilian Peevcf581372017-04-07 13:53:10 +01001271 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001272 if (hasInputBuf) {
1273 result.inputBuffer.streamId =
1274 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1275 result.inputBuffer.buffer = nullptr;
1276 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
1277 // skip acquire fence since it's no use to camera service
1278 if (hal_result->input_buffer->release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001279 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1280 handle->data[0] = hal_result->input_buffer->release_fence;
1281 result.inputBuffer.releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001282 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001283 result.inputBuffer.releaseFence = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001284 }
1285 } else {
1286 result.inputBuffer.streamId = -1;
1287 }
1288
1289 result.outputBuffers.resize(numOutputBufs);
1290 for (size_t i = 0; i < numOutputBufs; i++) {
1291 result.outputBuffers[i].streamId =
1292 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1293 result.outputBuffers[i].buffer = nullptr;
1294 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
1295 // skip acquire fence since it's of no use to camera service
1296 if (hal_result->output_buffers[i].release_fence != -1) {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001297 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
1298 handle->data[0] = hal_result->output_buffers[i].release_fence;
1299 result.outputBuffers[i].releaseFence = handle;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001300 } else {
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001301 result.outputBuffers[i].releaseFence = nullptr;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001302 }
1303 }
1304
1305 // Free inflight record/fences.
1306 // Do this before call back to camera service because camera service might jump to
1307 // configure_streams right after the processCaptureResult call so we need to finish
1308 // updating inflight queues first
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001309 if (numBufs > 0) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001310 Mutex::Autolock _l(d->mInflightLock);
1311 if (hasInputBuf) {
1312 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
1313 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001314 d->mInflightBuffers.erase(key);
1315 }
1316
1317 for (size_t i = 0; i < numOutputBufs; i++) {
1318 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
1319 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001320 d->mInflightBuffers.erase(key);
1321 }
1322
1323 if (d->mInflightBuffers.empty()) {
1324 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001325 }
1326 }
1327
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001328 d->mResultBatcher.processCaptureResult(result);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001329}
1330
1331void CameraDeviceSession::sNotify(
1332 const camera3_callback_ops *cb,
1333 const camera3_notify_msg *msg) {
1334 CameraDeviceSession *d =
1335 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
1336 NotifyMsg hidlMsg;
1337 convertToHidl(msg, &hidlMsg);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001338
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -08001339 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
1340 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001341 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
1342 ALOGE("%s: unknown stream ID %d reports an error!",
1343 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001344 return;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001345 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001346 }
Emilian Peevcf581372017-04-07 13:53:10 +01001347
1348 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
1349 switch (hidlMsg.msg.error.errorCode) {
1350 case ErrorCode::ERROR_DEVICE:
1351 case ErrorCode::ERROR_REQUEST:
1352 case ErrorCode::ERROR_RESULT: {
1353 Mutex::Autolock _l(d->mInflightLock);
1354 auto entry = d->mInflightAETriggerOverrides.find(
1355 hidlMsg.msg.error.frameNumber);
1356 if (d->mInflightAETriggerOverrides.end() != entry) {
1357 d->mInflightAETriggerOverrides.erase(
1358 hidlMsg.msg.error.frameNumber);
1359 }
Emilian Peeva13ac992017-04-10 12:02:17 +01001360
1361 auto boostEntry = d->mInflightRawBoostPresent.find(
1362 hidlMsg.msg.error.frameNumber);
1363 if (d->mInflightRawBoostPresent.end() != boostEntry) {
1364 d->mInflightRawBoostPresent.erase(
1365 hidlMsg.msg.error.frameNumber);
1366 }
1367
Emilian Peevcf581372017-04-07 13:53:10 +01001368 }
1369 break;
1370 case ErrorCode::ERROR_BUFFER:
1371 default:
1372 break;
1373 }
1374
1375 }
1376
Yin-Chia Yehbed3a942017-03-06 14:14:17 -08001377 d->mResultBatcher.notify(hidlMsg);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001378}
1379
1380} // namespace implementation
1381} // namespace V3_2
1382} // namespace device
1383} // namespace camera
1384} // namespace hardware
1385} // namespace android