blob: 03b605039746300e427017afccf9f7b3ff3ff5f2 [file] [log] [blame]
Emilian Peeve18057b2017-11-13 16:03:44 +00001/*
Shuzhen Wang82e36b32017-11-28 17:00:43 -08002 * Copyright (C) 2017-2018 The Android Open Source Project
Emilian Peeve18057b2017-11-13 16:03:44 +00003 *
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.4-impl"
18#include <android/log.h>
19
20#include <set>
21#include <utils/Trace.h>
22#include <hardware/gralloc.h>
23#include <hardware/gralloc1.h>
24#include "CameraDeviceSession.h"
Shuzhen Wang892e8262019-02-08 16:12:30 -080025#include "CameraModule.h"
Emilian Peeve18057b2017-11-13 16:03:44 +000026
27namespace android {
28namespace hardware {
29namespace camera {
30namespace device {
31namespace V3_4 {
32namespace implementation {
33
Shuzhen Wang892e8262019-02-08 16:12:30 -080034using ::android::hardware::camera::common::V1_0::helper::CameraModule;
35
Emilian Peeve18057b2017-11-13 16:03:44 +000036CameraDeviceSession::CameraDeviceSession(
37 camera3_device_t* device,
38 const camera_metadata_t* deviceInfo,
39 const sp<V3_2::ICameraDeviceCallback>& callback) :
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -080040 V3_3::implementation::CameraDeviceSession(device, deviceInfo, callback),
41 mResultBatcher_3_4(callback) {
42
43 mHasCallback_3_4 = false;
44
45 auto castResult = ICameraDeviceCallback::castFrom(callback);
46 if (castResult.isOk()) {
47 sp<ICameraDeviceCallback> callback3_4 = castResult;
48 if (callback3_4 != nullptr) {
49 process_capture_result = sProcessCaptureResult_3_4;
50 notify = sNotify_3_4;
51 mHasCallback_3_4 = true;
52 if (!mInitFail) {
53 mResultBatcher_3_4.setResultMetadataQueue(mResultMetadataQueue);
54 }
55 }
56 }
Shuzhen Wang448b7e32018-03-29 23:34:51 -070057
Emilian Peev59dd3df2018-05-03 13:25:51 +010058 mResultBatcher_3_4.setNumPartialResults(mNumPartialResults);
59
Shuzhen Wang892e8262019-02-08 16:12:30 -080060 // Parse and store current logical camera's physical ids.
61 (void)CameraModule::isLogicalMultiCamera(mDeviceInfo, &mPhysicalCameraIds);
62
Emilian Peeve18057b2017-11-13 16:03:44 +000063}
64
65CameraDeviceSession::~CameraDeviceSession() {
66}
67
68Return<void> CameraDeviceSession::configureStreams_3_4(
Shuzhen Wang82e36b32017-11-28 17:00:43 -080069 const StreamConfiguration& requestedConfiguration,
70 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070071 configureStreams_3_4_Impl(requestedConfiguration, _hidl_cb);
72 return Void();
73}
74
75void CameraDeviceSession::configureStreams_3_4_Impl(
76 const StreamConfiguration& requestedConfiguration,
77 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
78 uint32_t streamConfigCounter) {
Emilian Peeve18057b2017-11-13 16:03:44 +000079 Status status = initStatus();
80 HalStreamConfiguration outStreams;
81
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -080082 // If callback is 3.2, make sure no physical stream is configured
83 if (!mHasCallback_3_4) {
84 for (size_t i = 0; i < requestedConfiguration.streams.size(); i++) {
85 if (requestedConfiguration.streams[i].physicalCameraId.size() > 0) {
86 ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback",
87 __FUNCTION__);
88 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070089 return;
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -080090 }
91 }
92 }
93
Emilian Peeve18057b2017-11-13 16:03:44 +000094 // hold the inflight lock for entire configureStreams scope since there must not be any
95 // inflight request/results during stream configuration.
96 Mutex::Autolock _l(mInflightLock);
97 if (!mInflightBuffers.empty()) {
98 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
99 __FUNCTION__, mInflightBuffers.size());
100 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700101 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000102 }
103
104 if (!mInflightAETriggerOverrides.empty()) {
105 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
106 " trigger overrides!", __FUNCTION__,
107 mInflightAETriggerOverrides.size());
108 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700109 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000110 }
111
112 if (!mInflightRawBoostPresent.empty()) {
113 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
114 " boost overrides!", __FUNCTION__,
115 mInflightRawBoostPresent.size());
116 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700117 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000118 }
119
120 if (status != Status::OK) {
121 _hidl_cb(status, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700122 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000123 }
124
125 const camera_metadata_t *paramBuffer = nullptr;
126 if (0 < requestedConfiguration.sessionParams.size()) {
Emilian Peeve18057b2017-11-13 16:03:44 +0000127 V3_2::implementation::convertFromHidl(requestedConfiguration.sessionParams, &paramBuffer);
128 }
129
130 camera3_stream_configuration_t stream_list{};
Yin-Chia Yeh9e3079b2019-02-13 15:18:16 -0800131 // Block reading mStreamConfigCounter until configureStream returns
132 Mutex::Autolock _sccl(mStreamConfigCounterLock);
133 mStreamConfigCounter = streamConfigCounter;
Emilian Peeve18057b2017-11-13 16:03:44 +0000134 hidl_vec<camera3_stream_t*> streams;
135 stream_list.session_parameters = paramBuffer;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800136 if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
Emilian Peeve18057b2017-11-13 16:03:44 +0000137 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700138 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000139 }
140
141 ATRACE_BEGIN("camera3->configure_streams");
142 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
143 ATRACE_END();
144
145 // In case Hal returns error most likely it was not able to release
146 // the corresponding resources of the deleted streams.
147 if (ret == OK) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800148 postProcessConfigurationLocked_3_4(requestedConfiguration);
Yin-Chia Yeh7d1fdec2018-08-03 11:50:47 -0700149 } else {
150 postProcessConfigurationFailureLocked_3_4(requestedConfiguration);
Emilian Peeve18057b2017-11-13 16:03:44 +0000151 }
152
153 if (ret == -EINVAL) {
154 status = Status::ILLEGAL_ARGUMENT;
155 } else if (ret != OK) {
156 status = Status::INTERNAL_ERROR;
157 } else {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800158 V3_4::implementation::convertToHidl(stream_list, &outStreams);
Emilian Peeve18057b2017-11-13 16:03:44 +0000159 mFirstRequest = true;
160 }
161
162 _hidl_cb(status, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700163 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000164}
165
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800166bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
167 const StreamConfiguration& requestedConfiguration,
168 camera3_stream_configuration_t *stream_list /*out*/,
169 hidl_vec<camera3_stream_t*> *streams /*out*/) {
170
171 if ((stream_list == nullptr) || (streams == nullptr)) {
172 return false;
173 }
174
175 stream_list->operation_mode = (uint32_t) requestedConfiguration.operationMode;
176 stream_list->num_streams = requestedConfiguration.streams.size();
177 streams->resize(stream_list->num_streams);
178 stream_list->streams = streams->data();
179
180 for (uint32_t i = 0; i < stream_list->num_streams; i++) {
181 int id = requestedConfiguration.streams[i].v3_2.id;
182
183 if (mStreamMap.count(id) == 0) {
184 Camera3Stream stream;
185 convertFromHidl(requestedConfiguration.streams[i], &stream);
186 mStreamMap[id] = stream;
187 mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId;
188 mStreamMap[id].data_space = mapToLegacyDataspace(
189 mStreamMap[id].data_space);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800190 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
191 } else {
192 // width/height/format must not change, but usage/rotation might need to change
193 if (mStreamMap[id].stream_type !=
194 (int) requestedConfiguration.streams[i].v3_2.streamType ||
195 mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width ||
196 mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height ||
197 mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
198 mStreamMap[id].data_space !=
199 mapToLegacyDataspace( static_cast<android_dataspace_t> (
200 requestedConfiguration.streams[i].v3_2.dataSpace)) ||
201 mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) {
202 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
203 return false;
204 }
205 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
206 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
207 }
Emilian Peev5874bba2019-02-21 15:06:41 -0800208 // It is possible for the entry in 'mStreamMap' to get initialized by an older
209 // HIDL API. Make sure that the physical id is always initialized when using
210 // a more recent API call.
211 mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
212
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800213 (*streams)[i] = &mStreamMap[id];
214 }
215
Yin-Chia Yeh7d1fdec2018-08-03 11:50:47 -0700216 if (mFreeBufEarly) {
217 // Remove buffers of deleted streams
218 for(auto it = mStreamMap.begin(); it != mStreamMap.end(); it++) {
219 int id = it->first;
220 bool found = false;
221 for (const auto& stream : requestedConfiguration.streams) {
222 if (id == stream.v3_2.id) {
223 found = true;
224 break;
225 }
226 }
227 if (!found) {
228 // Unmap all buffers of deleted stream
229 cleanupBuffersLocked(id);
230 }
231 }
232 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800233 return true;
234}
235
236void CameraDeviceSession::postProcessConfigurationLocked_3_4(
237 const StreamConfiguration& requestedConfiguration) {
238 // delete unused streams, note we do this after adding new streams to ensure new stream
239 // will not have the same address as deleted stream, and HAL has a chance to reference
240 // the to be deleted stream in configure_streams call
241 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
242 int id = it->first;
243 bool found = false;
244 for (const auto& stream : requestedConfiguration.streams) {
245 if (id == stream.v3_2.id) {
246 found = true;
247 break;
248 }
249 }
250 if (!found) {
251 // Unmap all buffers of deleted stream
252 // in case the configuration call succeeds and HAL
253 // is able to release the corresponding resources too.
Yin-Chia Yeh7d1fdec2018-08-03 11:50:47 -0700254 if (!mFreeBufEarly) {
255 cleanupBuffersLocked(id);
256 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800257 it = mStreamMap.erase(it);
258 } else {
259 ++it;
260 }
261 }
262
263 // Track video streams
264 mVideoStreamIds.clear();
265 for (const auto& stream : requestedConfiguration.streams) {
266 if (stream.v3_2.streamType == StreamType::OUTPUT &&
267 stream.v3_2.usage &
268 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
269 mVideoStreamIds.push_back(stream.v3_2.id);
270 }
271 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800272 mResultBatcher_3_4.setBatchedStreams(mVideoStreamIds);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800273}
274
Yin-Chia Yeh7d1fdec2018-08-03 11:50:47 -0700275void CameraDeviceSession::postProcessConfigurationFailureLocked_3_4(
276 const StreamConfiguration& requestedConfiguration) {
277 if (mFreeBufEarly) {
278 // Re-build the buf cache entry for deleted streams
279 for(auto it = mStreamMap.begin(); it != mStreamMap.end(); it++) {
280 int id = it->first;
281 bool found = false;
282 for (const auto& stream : requestedConfiguration.streams) {
283 if (id == stream.v3_2.id) {
284 found = true;
285 break;
286 }
287 }
288 if (!found) {
289 mCirculatingBuffers.emplace(id, CirculatingBuffers{});
290 }
291 }
292 }
293}
294
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800295Return<void> CameraDeviceSession::processCaptureRequest_3_4(
Emilian Peevb75aa352018-01-17 11:00:54 +0000296 const hidl_vec<V3_4::CaptureRequest>& requests,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800297 const hidl_vec<V3_2::BufferCache>& cachesToRemove,
Emilian Peevb75aa352018-01-17 11:00:54 +0000298 ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800299 updateBufferCaches(cachesToRemove);
300
301 uint32_t numRequestProcessed = 0;
302 Status s = Status::OK;
303 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
304 s = processOneCaptureRequest_3_4(requests[i]);
305 if (s != Status::OK) {
306 break;
307 }
308 }
309
310 if (s == Status::OK && requests.size() > 1) {
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800311 mResultBatcher_3_4.registerBatch(requests[0].v3_2.frameNumber, requests.size());
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800312 }
313
314 _hidl_cb(s, numRequestProcessed);
315 return Void();
316}
317
Emilian Peevb75aa352018-01-17 11:00:54 +0000318Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800319 Status status = initStatus();
320 if (status != Status::OK) {
321 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
322 return status;
323 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800324 // If callback is 3.2, make sure there are no physical settings.
325 if (!mHasCallback_3_4) {
326 if (request.physicalCameraSettings.size() > 0) {
327 ALOGE("%s: trying to call processCaptureRequest_3_4 with physical camera id "
328 "and V3.2 callback", __FUNCTION__);
329 return Status::INTERNAL_ERROR;
330 }
331 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800332
333 camera3_capture_request_t halRequest;
Emilian Peevb75aa352018-01-17 11:00:54 +0000334 halRequest.frame_number = request.v3_2.frameNumber;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800335
336 bool converted = true;
337 V3_2::CameraMetadata settingsFmq; // settings from FMQ
Emilian Peevb75aa352018-01-17 11:00:54 +0000338 if (request.v3_2.fmqSettingsSize > 0) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800339 // non-blocking read; client must write metadata before calling
340 // processOneCaptureRequest
Emilian Peevb75aa352018-01-17 11:00:54 +0000341 settingsFmq.resize(request.v3_2.fmqSettingsSize);
342 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.v3_2.fmqSettingsSize);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800343 if (read) {
344 converted = V3_2::implementation::convertFromHidl(settingsFmq, &halRequest.settings);
345 } else {
346 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
347 converted = false;
348 }
349 } else {
Emilian Peevb75aa352018-01-17 11:00:54 +0000350 converted = V3_2::implementation::convertFromHidl(request.v3_2.settings,
351 &halRequest.settings);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800352 }
353
354 if (!converted) {
355 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
356 return Status::ILLEGAL_ARGUMENT;
357 }
358
359 if (mFirstRequest && halRequest.settings == nullptr) {
360 ALOGE("%s: capture request settings must not be null for first request!",
361 __FUNCTION__);
362 return Status::ILLEGAL_ARGUMENT;
363 }
364
365 hidl_vec<buffer_handle_t*> allBufPtrs;
366 hidl_vec<int> allFences;
Emilian Peevb75aa352018-01-17 11:00:54 +0000367 bool hasInputBuf = (request.v3_2.inputBuffer.streamId != -1 &&
368 request.v3_2.inputBuffer.bufferId != 0);
369 size_t numOutputBufs = request.v3_2.outputBuffers.size();
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800370 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
371
372 if (numOutputBufs == 0) {
373 ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
374 return Status::ILLEGAL_ARGUMENT;
375 }
376
Emilian Peevb75aa352018-01-17 11:00:54 +0000377 status = importRequest(request.v3_2, allBufPtrs, allFences);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800378 if (status != Status::OK) {
379 return status;
380 }
381
382 hidl_vec<camera3_stream_buffer_t> outHalBufs;
383 outHalBufs.resize(numOutputBufs);
384 bool aeCancelTriggerNeeded = false;
385 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
386 {
387 Mutex::Autolock _l(mInflightLock);
388 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000389 auto streamId = request.v3_2.inputBuffer.streamId;
390 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800391 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
392 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000393 allBufPtrs[numOutputBufs], request.v3_2.inputBuffer.status,
394 &mStreamMap[request.v3_2.inputBuffer.streamId], allFences[numOutputBufs],
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800395 &bufCache);
396 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
397 halRequest.input_buffer = &bufCache;
398 } else {
399 halRequest.input_buffer = nullptr;
400 }
401
402 halRequest.num_output_buffers = numOutputBufs;
403 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000404 auto streamId = request.v3_2.outputBuffers[i].streamId;
405 auto key = std::make_pair(streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800406 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
407 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000408 allBufPtrs[i], request.v3_2.outputBuffers[i].status,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800409 &mStreamMap[streamId], allFences[i],
410 &bufCache);
411 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
412 outHalBufs[i] = bufCache;
413 }
414 halRequest.output_buffers = outHalBufs.data();
415
416 AETriggerCancelOverride triggerOverride;
417 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
418 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
419 if (aeCancelTriggerNeeded) {
420 mInflightAETriggerOverrides[halRequest.frame_number] =
421 triggerOverride;
422 halRequest.settings = settingsOverride.getAndLock();
423 }
424 }
425
Emilian Peevb75aa352018-01-17 11:00:54 +0000426 std::vector<const char *> physicalCameraIds;
427 std::vector<const camera_metadata_t *> physicalCameraSettings;
428 std::vector<V3_2::CameraMetadata> physicalFmq;
429 size_t settingsCount = request.physicalCameraSettings.size();
430 if (settingsCount > 0) {
431 physicalCameraIds.reserve(settingsCount);
432 physicalCameraSettings.reserve(settingsCount);
433 physicalFmq.reserve(settingsCount);
434
435 for (size_t i = 0; i < settingsCount; i++) {
436 uint64_t settingsSize = request.physicalCameraSettings[i].fmqSettingsSize;
Emilian Peeve0c52bb2018-02-05 21:32:00 +0000437 const camera_metadata_t *settings = nullptr;
Emilian Peevb75aa352018-01-17 11:00:54 +0000438 if (settingsSize > 0) {
439 physicalFmq.push_back(V3_2::CameraMetadata(settingsSize));
440 bool read = mRequestMetadataQueue->read(physicalFmq[i].data(), settingsSize);
441 if (read) {
442 converted = V3_2::implementation::convertFromHidl(physicalFmq[i], &settings);
443 physicalCameraSettings.push_back(settings);
444 } else {
445 ALOGE("%s: physical camera settings metadata couldn't be read from fmq!",
446 __FUNCTION__);
447 converted = false;
448 }
449 } else {
450 converted = V3_2::implementation::convertFromHidl(
451 request.physicalCameraSettings[i].settings, &settings);
452 physicalCameraSettings.push_back(settings);
453 }
454
455 if (!converted) {
456 ALOGE("%s: physical camera settings metadata is corrupt!", __FUNCTION__);
457 return Status::ILLEGAL_ARGUMENT;
458 }
Emilian Peeve0c52bb2018-02-05 21:32:00 +0000459
460 if (mFirstRequest && settings == nullptr) {
461 ALOGE("%s: Individual request settings must not be null for first request!",
462 __FUNCTION__);
463 return Status::ILLEGAL_ARGUMENT;
464 }
465
Emilian Peevb75aa352018-01-17 11:00:54 +0000466 physicalCameraIds.push_back(request.physicalCameraSettings[i].physicalCameraId.c_str());
467 }
468 }
469 halRequest.num_physcam_settings = settingsCount;
470 halRequest.physcam_id = physicalCameraIds.data();
471 halRequest.physcam_settings = physicalCameraSettings.data();
472
473 ATRACE_ASYNC_BEGIN("frame capture", request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800474 ATRACE_BEGIN("camera3->process_capture_request");
475 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
476 ATRACE_END();
477 if (aeCancelTriggerNeeded) {
478 settingsOverride.unlock(halRequest.settings);
479 }
480 if (ret != OK) {
481 Mutex::Autolock _l(mInflightLock);
482 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
483
484 cleanupInflightFences(allFences, numBufs);
485 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000486 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800487 mInflightBuffers.erase(key);
488 }
489 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000490 auto key = std::make_pair(request.v3_2.outputBuffers[i].streamId,
491 request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800492 mInflightBuffers.erase(key);
493 }
494 if (aeCancelTriggerNeeded) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000495 mInflightAETriggerOverrides.erase(request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800496 }
Emilian Peevb75aa352018-01-17 11:00:54 +0000497
498 if (ret == BAD_VALUE) {
499 return Status::ILLEGAL_ARGUMENT;
500 } else {
501 return Status::INTERNAL_ERROR;
502 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800503 }
504
505 mFirstRequest = false;
506 return Status::OK;
507}
508
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800509/**
510 * Static callback forwarding methods from HAL to instance
511 */
512void CameraDeviceSession::sProcessCaptureResult_3_4(
513 const camera3_callback_ops *cb,
514 const camera3_capture_result *hal_result) {
515 CameraDeviceSession *d =
516 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
517
Shuzhen Wang17d817a2018-03-09 15:58:43 -0800518 CaptureResult result = {};
Yin-Chia Yeh090872a2018-05-17 15:53:30 -0700519 camera3_capture_result shadowResult;
520 bool handlePhysCam = (d->mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_5);
521 std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata> compactMds;
522 std::vector<const camera_metadata_t*> physCamMdArray;
523 sShrinkCaptureResult(&shadowResult, hal_result, &compactMds, &physCamMdArray, handlePhysCam);
524
525 status_t ret = d->constructCaptureResult(result.v3_2, &shadowResult);
Shuzhen Wang17d817a2018-03-09 15:58:43 -0800526 if (ret != OK) {
527 return;
528 }
529
Yin-Chia Yeh090872a2018-05-17 15:53:30 -0700530 if (handlePhysCam) {
531 if (shadowResult.num_physcam_metadata > d->mPhysicalCameraIds.size()) {
532 ALOGE("%s: Fatal: Invalid num_physcam_metadata %u", __FUNCTION__,
533 shadowResult.num_physcam_metadata);
Shuzhen Wang448b7e32018-03-29 23:34:51 -0700534 return;
535 }
Yin-Chia Yeh090872a2018-05-17 15:53:30 -0700536 result.physicalCameraMetadata.resize(shadowResult.num_physcam_metadata);
537 for (uint32_t i = 0; i < shadowResult.num_physcam_metadata; i++) {
538 std::string physicalId = shadowResult.physcam_ids[i];
539 if (d->mPhysicalCameraIds.find(physicalId) == d->mPhysicalCameraIds.end()) {
540 ALOGE("%s: Fatal: Invalid physcam_ids[%u]: %s", __FUNCTION__,
541 i, shadowResult.physcam_ids[i]);
542 return;
543 }
544 V3_2::CameraMetadata physicalMetadata;
545 V3_2::implementation::convertToHidl(
546 shadowResult.physcam_metadata[i], &physicalMetadata);
547 PhysicalCameraMetadata physicalCameraMetadata = {
548 .fmqMetadataSize = 0,
549 .physicalCameraId = physicalId,
550 .metadata = physicalMetadata };
551 result.physicalCameraMetadata[i] = physicalCameraMetadata;
552 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800553 }
554 d->mResultBatcher_3_4.processCaptureResult_3_4(result);
555}
556
557void CameraDeviceSession::sNotify_3_4(
558 const camera3_callback_ops *cb,
559 const camera3_notify_msg *msg) {
560 CameraDeviceSession *d =
561 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
562 V3_2::NotifyMsg hidlMsg;
563 V3_2::implementation::convertToHidl(msg, &hidlMsg);
564
565 if (hidlMsg.type == (V3_2::MsgType) CAMERA3_MSG_ERROR &&
566 hidlMsg.msg.error.errorStreamId != -1) {
567 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
568 ALOGE("%s: unknown stream ID %d reports an error!",
569 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
570 return;
571 }
572 }
573
574 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
575 switch (hidlMsg.msg.error.errorCode) {
576 case V3_2::ErrorCode::ERROR_DEVICE:
577 case V3_2::ErrorCode::ERROR_REQUEST:
578 case V3_2::ErrorCode::ERROR_RESULT: {
579 Mutex::Autolock _l(d->mInflightLock);
580 auto entry = d->mInflightAETriggerOverrides.find(
581 hidlMsg.msg.error.frameNumber);
582 if (d->mInflightAETriggerOverrides.end() != entry) {
583 d->mInflightAETriggerOverrides.erase(
584 hidlMsg.msg.error.frameNumber);
585 }
586
587 auto boostEntry = d->mInflightRawBoostPresent.find(
588 hidlMsg.msg.error.frameNumber);
589 if (d->mInflightRawBoostPresent.end() != boostEntry) {
590 d->mInflightRawBoostPresent.erase(
591 hidlMsg.msg.error.frameNumber);
592 }
593
594 }
595 break;
596 case V3_2::ErrorCode::ERROR_BUFFER:
597 default:
598 break;
599 }
600
601 }
602
603 d->mResultBatcher_3_4.notify(hidlMsg);
604}
605
606CameraDeviceSession::ResultBatcher_3_4::ResultBatcher_3_4(
607 const sp<V3_2::ICameraDeviceCallback>& callback) :
608 V3_3::implementation::CameraDeviceSession::ResultBatcher(callback) {
609 auto castResult = ICameraDeviceCallback::castFrom(callback);
610 if (castResult.isOk()) {
611 mCallback_3_4 = castResult;
612 }
613}
614
615void CameraDeviceSession::ResultBatcher_3_4::processCaptureResult_3_4(CaptureResult& result) {
616 auto pair = getBatch(result.v3_2.frameNumber);
617 int batchIdx = pair.first;
618 if (batchIdx == NOT_BATCHED) {
619 processOneCaptureResult_3_4(result);
620 return;
621 }
622 std::shared_ptr<InflightBatch> batch = pair.second;
623 {
624 Mutex::Autolock _l(batch->mLock);
625 // Check if the batch is removed (mostly by notify error) before lock was acquired
626 if (batch->mRemoved) {
627 // Fall back to non-batch path
628 processOneCaptureResult_3_4(result);
629 return;
630 }
631
632 // queue metadata
633 if (result.v3_2.result.size() != 0) {
634 // Save a copy of metadata
635 batch->mResultMds[result.v3_2.partialResult].mMds.push_back(
636 std::make_pair(result.v3_2.frameNumber, result.v3_2.result));
637 }
638
639 // queue buffer
640 std::vector<int> filledStreams;
641 std::vector<V3_2::StreamBuffer> nonBatchedBuffers;
642 for (auto& buffer : result.v3_2.outputBuffers) {
643 auto it = batch->mBatchBufs.find(buffer.streamId);
644 if (it != batch->mBatchBufs.end()) {
645 InflightBatch::BufferBatch& bb = it->second;
646 pushStreamBuffer(std::move(buffer), bb.mBuffers);
647 filledStreams.push_back(buffer.streamId);
648 } else {
649 pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
650 }
651 }
652
653 // send non-batched buffers up
654 if (nonBatchedBuffers.size() > 0 || result.v3_2.inputBuffer.streamId != -1) {
655 CaptureResult nonBatchedResult;
656 nonBatchedResult.v3_2.frameNumber = result.v3_2.frameNumber;
657 nonBatchedResult.v3_2.fmqResultSize = 0;
658 nonBatchedResult.v3_2.outputBuffers.resize(nonBatchedBuffers.size());
659 for (size_t i = 0; i < nonBatchedBuffers.size(); i++) {
660 moveStreamBuffer(
661 std::move(nonBatchedBuffers[i]), nonBatchedResult.v3_2.outputBuffers[i]);
662 }
663 moveStreamBuffer(std::move(result.v3_2.inputBuffer), nonBatchedResult.v3_2.inputBuffer);
664 nonBatchedResult.v3_2.partialResult = 0; // 0 for buffer only results
665 processOneCaptureResult_3_4(nonBatchedResult);
666 }
667
668 if (result.v3_2.frameNumber == batch->mLastFrame) {
669 // Send data up
670 if (result.v3_2.partialResult > 0) {
671 sendBatchMetadataLocked(batch, result.v3_2.partialResult);
672 }
673 // send buffer up
674 if (filledStreams.size() > 0) {
675 sendBatchBuffersLocked(batch, filledStreams);
676 }
677 }
678 } // end of batch lock scope
679
680 // see if the batch is complete
681 if (result.v3_2.frameNumber == batch->mLastFrame) {
682 checkAndRemoveFirstBatch();
683 }
684}
685
686void CameraDeviceSession::ResultBatcher_3_4::processOneCaptureResult_3_4(CaptureResult& result) {
687 hidl_vec<CaptureResult> results;
688 results.resize(1);
689 results[0] = std::move(result);
690 invokeProcessCaptureResultCallback_3_4(results, /* tryWriteFmq */true);
691 freeReleaseFences_3_4(results);
692 return;
693}
694
695void CameraDeviceSession::ResultBatcher_3_4::invokeProcessCaptureResultCallback_3_4(
696 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
697 if (mProcessCaptureResultLock.tryLock() != OK) {
698 ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
699 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
700 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
701 __FUNCTION__);
702 return;
703 }
704 }
705 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
706 for (CaptureResult &result : results) {
707 if (result.v3_2.result.size() > 0) {
708 if (mResultMetadataQueue->write(result.v3_2.result.data(),
709 result.v3_2.result.size())) {
710 result.v3_2.fmqResultSize = result.v3_2.result.size();
711 result.v3_2.result.resize(0);
712 } else {
713 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
714 result.v3_2.fmqResultSize = 0;
715 }
716 }
717
718 for (auto& onePhysMetadata : result.physicalCameraMetadata) {
719 if (mResultMetadataQueue->write(onePhysMetadata.metadata.data(),
720 onePhysMetadata.metadata.size())) {
721 onePhysMetadata.fmqMetadataSize = onePhysMetadata.metadata.size();
722 onePhysMetadata.metadata.resize(0);
723 } else {
724 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
725 onePhysMetadata.fmqMetadataSize = 0;
726 }
727 }
728 }
729 }
730 mCallback_3_4->processCaptureResult_3_4(results);
731 mProcessCaptureResultLock.unlock();
732}
733
734void CameraDeviceSession::ResultBatcher_3_4::freeReleaseFences_3_4(hidl_vec<CaptureResult>& results) {
735 for (auto& result : results) {
736 if (result.v3_2.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
737 native_handle_t* handle = const_cast<native_handle_t*>(
738 result.v3_2.inputBuffer.releaseFence.getNativeHandle());
739 native_handle_close(handle);
740 native_handle_delete(handle);
741 }
742 for (auto& buf : result.v3_2.outputBuffers) {
743 if (buf.releaseFence.getNativeHandle() != nullptr) {
744 native_handle_t* handle = const_cast<native_handle_t*>(
745 buf.releaseFence.getNativeHandle());
746 native_handle_close(handle);
747 native_handle_delete(handle);
748 }
749 }
750 }
751 return;
752}
753
Emilian Peeve18057b2017-11-13 16:03:44 +0000754} // namespace implementation
755} // namespace V3_4
756} // namespace device
757} // namespace camera
758} // namespace hardware
759} // namespace android