blob: e52577cfb99a17e9d403bef18fabd03e7b3cc1fe [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"
25
26namespace android {
27namespace hardware {
28namespace camera {
29namespace device {
30namespace V3_4 {
31namespace implementation {
32
33CameraDeviceSession::CameraDeviceSession(
34 camera3_device_t* device,
35 const camera_metadata_t* deviceInfo,
36 const sp<V3_2::ICameraDeviceCallback>& callback) :
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -080037 V3_3::implementation::CameraDeviceSession(device, deviceInfo, callback),
38 mResultBatcher_3_4(callback) {
39
40 mHasCallback_3_4 = false;
41
42 auto castResult = ICameraDeviceCallback::castFrom(callback);
43 if (castResult.isOk()) {
44 sp<ICameraDeviceCallback> callback3_4 = castResult;
45 if (callback3_4 != nullptr) {
46 process_capture_result = sProcessCaptureResult_3_4;
47 notify = sNotify_3_4;
48 mHasCallback_3_4 = true;
49 if (!mInitFail) {
50 mResultBatcher_3_4.setResultMetadataQueue(mResultMetadataQueue);
51 }
52 }
53 }
Shuzhen Wang448b7e32018-03-29 23:34:51 -070054
Emilian Peev59dd3df2018-05-03 13:25:51 +010055 mResultBatcher_3_4.setNumPartialResults(mNumPartialResults);
56
Shuzhen Wang448b7e32018-03-29 23:34:51 -070057 camera_metadata_entry_t capabilities =
58 mDeviceInfo.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
59 bool isLogicalMultiCamera = false;
60 for (size_t i = 0; i < capabilities.count; i++) {
61 if (capabilities.data.u8[i] ==
62 ANDROID_REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA) {
63 isLogicalMultiCamera = true;
64 break;
65 }
66 }
67 if (isLogicalMultiCamera) {
68 camera_metadata_entry entry =
69 mDeviceInfo.find(ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS);
70 const uint8_t* ids = entry.data.u8;
71 size_t start = 0;
72 for (size_t i = 0; i < entry.count; ++i) {
73 if (ids[i] == '\0') {
74 if (start != i) {
75 const char* physicalId = reinterpret_cast<const char*>(ids+start);
76 mPhysicalCameraIds.emplace(physicalId);
77 }
78 start = i + 1;
79 }
80 }
81 }
Emilian Peeve18057b2017-11-13 16:03:44 +000082}
83
84CameraDeviceSession::~CameraDeviceSession() {
85}
86
87Return<void> CameraDeviceSession::configureStreams_3_4(
Shuzhen Wang82e36b32017-11-28 17:00:43 -080088 const StreamConfiguration& requestedConfiguration,
89 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070090 configureStreams_3_4_Impl(requestedConfiguration, _hidl_cb);
91 return Void();
92}
93
94void CameraDeviceSession::configureStreams_3_4_Impl(
95 const StreamConfiguration& requestedConfiguration,
96 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
97 uint32_t streamConfigCounter) {
Emilian Peeve18057b2017-11-13 16:03:44 +000098 Status status = initStatus();
99 HalStreamConfiguration outStreams;
100
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800101 // If callback is 3.2, make sure no physical stream is configured
102 if (!mHasCallback_3_4) {
103 for (size_t i = 0; i < requestedConfiguration.streams.size(); i++) {
104 if (requestedConfiguration.streams[i].physicalCameraId.size() > 0) {
105 ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback",
106 __FUNCTION__);
107 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700108 return;
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800109 }
110 }
111 }
112
Emilian Peeve18057b2017-11-13 16:03:44 +0000113 // hold the inflight lock for entire configureStreams scope since there must not be any
114 // inflight request/results during stream configuration.
115 Mutex::Autolock _l(mInflightLock);
116 if (!mInflightBuffers.empty()) {
117 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
118 __FUNCTION__, mInflightBuffers.size());
119 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700120 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000121 }
122
123 if (!mInflightAETriggerOverrides.empty()) {
124 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
125 " trigger overrides!", __FUNCTION__,
126 mInflightAETriggerOverrides.size());
127 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700128 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000129 }
130
131 if (!mInflightRawBoostPresent.empty()) {
132 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
133 " boost overrides!", __FUNCTION__,
134 mInflightRawBoostPresent.size());
135 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700136 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000137 }
138
139 if (status != Status::OK) {
140 _hidl_cb(status, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700141 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000142 }
143
144 const camera_metadata_t *paramBuffer = nullptr;
145 if (0 < requestedConfiguration.sessionParams.size()) {
Emilian Peeve18057b2017-11-13 16:03:44 +0000146 V3_2::implementation::convertFromHidl(requestedConfiguration.sessionParams, &paramBuffer);
147 }
148
149 camera3_stream_configuration_t stream_list{};
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700150 stream_list.stream_configuration_counter = streamConfigCounter;
Emilian Peeve18057b2017-11-13 16:03:44 +0000151 hidl_vec<camera3_stream_t*> streams;
152 stream_list.session_parameters = paramBuffer;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800153 if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
Emilian Peeve18057b2017-11-13 16:03:44 +0000154 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700155 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000156 }
157
158 ATRACE_BEGIN("camera3->configure_streams");
159 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
160 ATRACE_END();
161
162 // In case Hal returns error most likely it was not able to release
163 // the corresponding resources of the deleted streams.
164 if (ret == OK) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800165 postProcessConfigurationLocked_3_4(requestedConfiguration);
Yin-Chia Yeh7d1fdec2018-08-03 11:50:47 -0700166 } else {
167 postProcessConfigurationFailureLocked_3_4(requestedConfiguration);
Emilian Peeve18057b2017-11-13 16:03:44 +0000168 }
169
170 if (ret == -EINVAL) {
171 status = Status::ILLEGAL_ARGUMENT;
172 } else if (ret != OK) {
173 status = Status::INTERNAL_ERROR;
174 } else {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800175 V3_4::implementation::convertToHidl(stream_list, &outStreams);
Emilian Peeve18057b2017-11-13 16:03:44 +0000176 mFirstRequest = true;
177 }
178
179 _hidl_cb(status, outStreams);
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700180 return;
Emilian Peeve18057b2017-11-13 16:03:44 +0000181}
182
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800183bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
184 const StreamConfiguration& requestedConfiguration,
185 camera3_stream_configuration_t *stream_list /*out*/,
186 hidl_vec<camera3_stream_t*> *streams /*out*/) {
187
188 if ((stream_list == nullptr) || (streams == nullptr)) {
189 return false;
190 }
191
192 stream_list->operation_mode = (uint32_t) requestedConfiguration.operationMode;
193 stream_list->num_streams = requestedConfiguration.streams.size();
194 streams->resize(stream_list->num_streams);
195 stream_list->streams = streams->data();
196
197 for (uint32_t i = 0; i < stream_list->num_streams; i++) {
198 int id = requestedConfiguration.streams[i].v3_2.id;
199
200 if (mStreamMap.count(id) == 0) {
201 Camera3Stream stream;
202 convertFromHidl(requestedConfiguration.streams[i], &stream);
203 mStreamMap[id] = stream;
204 mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId;
205 mStreamMap[id].data_space = mapToLegacyDataspace(
206 mStreamMap[id].data_space);
207 mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
208 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
209 } else {
210 // width/height/format must not change, but usage/rotation might need to change
211 if (mStreamMap[id].stream_type !=
212 (int) requestedConfiguration.streams[i].v3_2.streamType ||
213 mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width ||
214 mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height ||
215 mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
216 mStreamMap[id].data_space !=
217 mapToLegacyDataspace( static_cast<android_dataspace_t> (
218 requestedConfiguration.streams[i].v3_2.dataSpace)) ||
219 mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) {
220 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
221 return false;
222 }
223 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
224 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
225 }
226 (*streams)[i] = &mStreamMap[id];
227 }
228
Yin-Chia Yeh7d1fdec2018-08-03 11:50:47 -0700229 if (mFreeBufEarly) {
230 // Remove buffers of deleted streams
231 for(auto it = mStreamMap.begin(); it != mStreamMap.end(); it++) {
232 int id = it->first;
233 bool found = false;
234 for (const auto& stream : requestedConfiguration.streams) {
235 if (id == stream.v3_2.id) {
236 found = true;
237 break;
238 }
239 }
240 if (!found) {
241 // Unmap all buffers of deleted stream
242 cleanupBuffersLocked(id);
243 }
244 }
245 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800246 return true;
247}
248
249void CameraDeviceSession::postProcessConfigurationLocked_3_4(
250 const StreamConfiguration& requestedConfiguration) {
251 // delete unused streams, note we do this after adding new streams to ensure new stream
252 // will not have the same address as deleted stream, and HAL has a chance to reference
253 // the to be deleted stream in configure_streams call
254 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
255 int id = it->first;
256 bool found = false;
257 for (const auto& stream : requestedConfiguration.streams) {
258 if (id == stream.v3_2.id) {
259 found = true;
260 break;
261 }
262 }
263 if (!found) {
264 // Unmap all buffers of deleted stream
265 // in case the configuration call succeeds and HAL
266 // is able to release the corresponding resources too.
Yin-Chia Yeh7d1fdec2018-08-03 11:50:47 -0700267 if (!mFreeBufEarly) {
268 cleanupBuffersLocked(id);
269 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800270 it = mStreamMap.erase(it);
271 } else {
272 ++it;
273 }
274 }
275
276 // Track video streams
277 mVideoStreamIds.clear();
278 for (const auto& stream : requestedConfiguration.streams) {
279 if (stream.v3_2.streamType == StreamType::OUTPUT &&
280 stream.v3_2.usage &
281 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
282 mVideoStreamIds.push_back(stream.v3_2.id);
283 }
284 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800285 mResultBatcher_3_4.setBatchedStreams(mVideoStreamIds);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800286}
287
Yin-Chia Yeh7d1fdec2018-08-03 11:50:47 -0700288void CameraDeviceSession::postProcessConfigurationFailureLocked_3_4(
289 const StreamConfiguration& requestedConfiguration) {
290 if (mFreeBufEarly) {
291 // Re-build the buf cache entry for deleted streams
292 for(auto it = mStreamMap.begin(); it != mStreamMap.end(); it++) {
293 int id = it->first;
294 bool found = false;
295 for (const auto& stream : requestedConfiguration.streams) {
296 if (id == stream.v3_2.id) {
297 found = true;
298 break;
299 }
300 }
301 if (!found) {
302 mCirculatingBuffers.emplace(id, CirculatingBuffers{});
303 }
304 }
305 }
306}
307
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800308Return<void> CameraDeviceSession::processCaptureRequest_3_4(
Emilian Peevb75aa352018-01-17 11:00:54 +0000309 const hidl_vec<V3_4::CaptureRequest>& requests,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800310 const hidl_vec<V3_2::BufferCache>& cachesToRemove,
Emilian Peevb75aa352018-01-17 11:00:54 +0000311 ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800312 updateBufferCaches(cachesToRemove);
313
314 uint32_t numRequestProcessed = 0;
315 Status s = Status::OK;
316 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
317 s = processOneCaptureRequest_3_4(requests[i]);
318 if (s != Status::OK) {
319 break;
320 }
321 }
322
323 if (s == Status::OK && requests.size() > 1) {
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800324 mResultBatcher_3_4.registerBatch(requests[0].v3_2.frameNumber, requests.size());
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800325 }
326
327 _hidl_cb(s, numRequestProcessed);
328 return Void();
329}
330
Emilian Peevb75aa352018-01-17 11:00:54 +0000331Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800332 Status status = initStatus();
333 if (status != Status::OK) {
334 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
335 return status;
336 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800337 // If callback is 3.2, make sure there are no physical settings.
338 if (!mHasCallback_3_4) {
339 if (request.physicalCameraSettings.size() > 0) {
340 ALOGE("%s: trying to call processCaptureRequest_3_4 with physical camera id "
341 "and V3.2 callback", __FUNCTION__);
342 return Status::INTERNAL_ERROR;
343 }
344 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800345
346 camera3_capture_request_t halRequest;
Emilian Peevb75aa352018-01-17 11:00:54 +0000347 halRequest.frame_number = request.v3_2.frameNumber;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800348
349 bool converted = true;
350 V3_2::CameraMetadata settingsFmq; // settings from FMQ
Emilian Peevb75aa352018-01-17 11:00:54 +0000351 if (request.v3_2.fmqSettingsSize > 0) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800352 // non-blocking read; client must write metadata before calling
353 // processOneCaptureRequest
Emilian Peevb75aa352018-01-17 11:00:54 +0000354 settingsFmq.resize(request.v3_2.fmqSettingsSize);
355 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.v3_2.fmqSettingsSize);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800356 if (read) {
357 converted = V3_2::implementation::convertFromHidl(settingsFmq, &halRequest.settings);
358 } else {
359 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
360 converted = false;
361 }
362 } else {
Emilian Peevb75aa352018-01-17 11:00:54 +0000363 converted = V3_2::implementation::convertFromHidl(request.v3_2.settings,
364 &halRequest.settings);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800365 }
366
367 if (!converted) {
368 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
369 return Status::ILLEGAL_ARGUMENT;
370 }
371
372 if (mFirstRequest && halRequest.settings == nullptr) {
373 ALOGE("%s: capture request settings must not be null for first request!",
374 __FUNCTION__);
375 return Status::ILLEGAL_ARGUMENT;
376 }
377
378 hidl_vec<buffer_handle_t*> allBufPtrs;
379 hidl_vec<int> allFences;
Emilian Peevb75aa352018-01-17 11:00:54 +0000380 bool hasInputBuf = (request.v3_2.inputBuffer.streamId != -1 &&
381 request.v3_2.inputBuffer.bufferId != 0);
382 size_t numOutputBufs = request.v3_2.outputBuffers.size();
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800383 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
384
385 if (numOutputBufs == 0) {
386 ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
387 return Status::ILLEGAL_ARGUMENT;
388 }
389
Emilian Peevb75aa352018-01-17 11:00:54 +0000390 status = importRequest(request.v3_2, allBufPtrs, allFences);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800391 if (status != Status::OK) {
392 return status;
393 }
394
395 hidl_vec<camera3_stream_buffer_t> outHalBufs;
396 outHalBufs.resize(numOutputBufs);
397 bool aeCancelTriggerNeeded = false;
398 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
399 {
400 Mutex::Autolock _l(mInflightLock);
401 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000402 auto streamId = request.v3_2.inputBuffer.streamId;
403 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800404 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
405 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000406 allBufPtrs[numOutputBufs], request.v3_2.inputBuffer.status,
407 &mStreamMap[request.v3_2.inputBuffer.streamId], allFences[numOutputBufs],
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800408 &bufCache);
409 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
410 halRequest.input_buffer = &bufCache;
411 } else {
412 halRequest.input_buffer = nullptr;
413 }
414
415 halRequest.num_output_buffers = numOutputBufs;
416 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000417 auto streamId = request.v3_2.outputBuffers[i].streamId;
418 auto key = std::make_pair(streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800419 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
420 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000421 allBufPtrs[i], request.v3_2.outputBuffers[i].status,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800422 &mStreamMap[streamId], allFences[i],
423 &bufCache);
424 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
425 outHalBufs[i] = bufCache;
426 }
427 halRequest.output_buffers = outHalBufs.data();
428
429 AETriggerCancelOverride triggerOverride;
430 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
431 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
432 if (aeCancelTriggerNeeded) {
433 mInflightAETriggerOverrides[halRequest.frame_number] =
434 triggerOverride;
435 halRequest.settings = settingsOverride.getAndLock();
436 }
437 }
438
Emilian Peevb75aa352018-01-17 11:00:54 +0000439 std::vector<const char *> physicalCameraIds;
440 std::vector<const camera_metadata_t *> physicalCameraSettings;
441 std::vector<V3_2::CameraMetadata> physicalFmq;
442 size_t settingsCount = request.physicalCameraSettings.size();
443 if (settingsCount > 0) {
444 physicalCameraIds.reserve(settingsCount);
445 physicalCameraSettings.reserve(settingsCount);
446 physicalFmq.reserve(settingsCount);
447
448 for (size_t i = 0; i < settingsCount; i++) {
449 uint64_t settingsSize = request.physicalCameraSettings[i].fmqSettingsSize;
Emilian Peeve0c52bb2018-02-05 21:32:00 +0000450 const camera_metadata_t *settings = nullptr;
Emilian Peevb75aa352018-01-17 11:00:54 +0000451 if (settingsSize > 0) {
452 physicalFmq.push_back(V3_2::CameraMetadata(settingsSize));
453 bool read = mRequestMetadataQueue->read(physicalFmq[i].data(), settingsSize);
454 if (read) {
455 converted = V3_2::implementation::convertFromHidl(physicalFmq[i], &settings);
456 physicalCameraSettings.push_back(settings);
457 } else {
458 ALOGE("%s: physical camera settings metadata couldn't be read from fmq!",
459 __FUNCTION__);
460 converted = false;
461 }
462 } else {
463 converted = V3_2::implementation::convertFromHidl(
464 request.physicalCameraSettings[i].settings, &settings);
465 physicalCameraSettings.push_back(settings);
466 }
467
468 if (!converted) {
469 ALOGE("%s: physical camera settings metadata is corrupt!", __FUNCTION__);
470 return Status::ILLEGAL_ARGUMENT;
471 }
Emilian Peeve0c52bb2018-02-05 21:32:00 +0000472
473 if (mFirstRequest && settings == nullptr) {
474 ALOGE("%s: Individual request settings must not be null for first request!",
475 __FUNCTION__);
476 return Status::ILLEGAL_ARGUMENT;
477 }
478
Emilian Peevb75aa352018-01-17 11:00:54 +0000479 physicalCameraIds.push_back(request.physicalCameraSettings[i].physicalCameraId.c_str());
480 }
481 }
482 halRequest.num_physcam_settings = settingsCount;
483 halRequest.physcam_id = physicalCameraIds.data();
484 halRequest.physcam_settings = physicalCameraSettings.data();
485
486 ATRACE_ASYNC_BEGIN("frame capture", request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800487 ATRACE_BEGIN("camera3->process_capture_request");
488 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
489 ATRACE_END();
490 if (aeCancelTriggerNeeded) {
491 settingsOverride.unlock(halRequest.settings);
492 }
493 if (ret != OK) {
494 Mutex::Autolock _l(mInflightLock);
495 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
496
497 cleanupInflightFences(allFences, numBufs);
498 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000499 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800500 mInflightBuffers.erase(key);
501 }
502 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000503 auto key = std::make_pair(request.v3_2.outputBuffers[i].streamId,
504 request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800505 mInflightBuffers.erase(key);
506 }
507 if (aeCancelTriggerNeeded) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000508 mInflightAETriggerOverrides.erase(request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800509 }
Emilian Peevb75aa352018-01-17 11:00:54 +0000510
511 if (ret == BAD_VALUE) {
512 return Status::ILLEGAL_ARGUMENT;
513 } else {
514 return Status::INTERNAL_ERROR;
515 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800516 }
517
518 mFirstRequest = false;
519 return Status::OK;
520}
521
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800522/**
523 * Static callback forwarding methods from HAL to instance
524 */
525void CameraDeviceSession::sProcessCaptureResult_3_4(
526 const camera3_callback_ops *cb,
527 const camera3_capture_result *hal_result) {
528 CameraDeviceSession *d =
529 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
530
Shuzhen Wang17d817a2018-03-09 15:58:43 -0800531 CaptureResult result = {};
Yin-Chia Yeh090872a2018-05-17 15:53:30 -0700532 camera3_capture_result shadowResult;
533 bool handlePhysCam = (d->mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_5);
534 std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata> compactMds;
535 std::vector<const camera_metadata_t*> physCamMdArray;
536 sShrinkCaptureResult(&shadowResult, hal_result, &compactMds, &physCamMdArray, handlePhysCam);
537
538 status_t ret = d->constructCaptureResult(result.v3_2, &shadowResult);
Shuzhen Wang17d817a2018-03-09 15:58:43 -0800539 if (ret != OK) {
540 return;
541 }
542
Yin-Chia Yeh090872a2018-05-17 15:53:30 -0700543 if (handlePhysCam) {
544 if (shadowResult.num_physcam_metadata > d->mPhysicalCameraIds.size()) {
545 ALOGE("%s: Fatal: Invalid num_physcam_metadata %u", __FUNCTION__,
546 shadowResult.num_physcam_metadata);
Shuzhen Wang448b7e32018-03-29 23:34:51 -0700547 return;
548 }
Yin-Chia Yeh090872a2018-05-17 15:53:30 -0700549 result.physicalCameraMetadata.resize(shadowResult.num_physcam_metadata);
550 for (uint32_t i = 0; i < shadowResult.num_physcam_metadata; i++) {
551 std::string physicalId = shadowResult.physcam_ids[i];
552 if (d->mPhysicalCameraIds.find(physicalId) == d->mPhysicalCameraIds.end()) {
553 ALOGE("%s: Fatal: Invalid physcam_ids[%u]: %s", __FUNCTION__,
554 i, shadowResult.physcam_ids[i]);
555 return;
556 }
557 V3_2::CameraMetadata physicalMetadata;
558 V3_2::implementation::convertToHidl(
559 shadowResult.physcam_metadata[i], &physicalMetadata);
560 PhysicalCameraMetadata physicalCameraMetadata = {
561 .fmqMetadataSize = 0,
562 .physicalCameraId = physicalId,
563 .metadata = physicalMetadata };
564 result.physicalCameraMetadata[i] = physicalCameraMetadata;
565 }
Shuzhen Wang39cf8fd2017-12-29 16:17:09 -0800566 }
567 d->mResultBatcher_3_4.processCaptureResult_3_4(result);
568}
569
570void CameraDeviceSession::sNotify_3_4(
571 const camera3_callback_ops *cb,
572 const camera3_notify_msg *msg) {
573 CameraDeviceSession *d =
574 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
575 V3_2::NotifyMsg hidlMsg;
576 V3_2::implementation::convertToHidl(msg, &hidlMsg);
577
578 if (hidlMsg.type == (V3_2::MsgType) CAMERA3_MSG_ERROR &&
579 hidlMsg.msg.error.errorStreamId != -1) {
580 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
581 ALOGE("%s: unknown stream ID %d reports an error!",
582 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
583 return;
584 }
585 }
586
587 if (static_cast<camera3_msg_type_t>(hidlMsg.type) == CAMERA3_MSG_ERROR) {
588 switch (hidlMsg.msg.error.errorCode) {
589 case V3_2::ErrorCode::ERROR_DEVICE:
590 case V3_2::ErrorCode::ERROR_REQUEST:
591 case V3_2::ErrorCode::ERROR_RESULT: {
592 Mutex::Autolock _l(d->mInflightLock);
593 auto entry = d->mInflightAETriggerOverrides.find(
594 hidlMsg.msg.error.frameNumber);
595 if (d->mInflightAETriggerOverrides.end() != entry) {
596 d->mInflightAETriggerOverrides.erase(
597 hidlMsg.msg.error.frameNumber);
598 }
599
600 auto boostEntry = d->mInflightRawBoostPresent.find(
601 hidlMsg.msg.error.frameNumber);
602 if (d->mInflightRawBoostPresent.end() != boostEntry) {
603 d->mInflightRawBoostPresent.erase(
604 hidlMsg.msg.error.frameNumber);
605 }
606
607 }
608 break;
609 case V3_2::ErrorCode::ERROR_BUFFER:
610 default:
611 break;
612 }
613
614 }
615
616 d->mResultBatcher_3_4.notify(hidlMsg);
617}
618
619CameraDeviceSession::ResultBatcher_3_4::ResultBatcher_3_4(
620 const sp<V3_2::ICameraDeviceCallback>& callback) :
621 V3_3::implementation::CameraDeviceSession::ResultBatcher(callback) {
622 auto castResult = ICameraDeviceCallback::castFrom(callback);
623 if (castResult.isOk()) {
624 mCallback_3_4 = castResult;
625 }
626}
627
628void CameraDeviceSession::ResultBatcher_3_4::processCaptureResult_3_4(CaptureResult& result) {
629 auto pair = getBatch(result.v3_2.frameNumber);
630 int batchIdx = pair.first;
631 if (batchIdx == NOT_BATCHED) {
632 processOneCaptureResult_3_4(result);
633 return;
634 }
635 std::shared_ptr<InflightBatch> batch = pair.second;
636 {
637 Mutex::Autolock _l(batch->mLock);
638 // Check if the batch is removed (mostly by notify error) before lock was acquired
639 if (batch->mRemoved) {
640 // Fall back to non-batch path
641 processOneCaptureResult_3_4(result);
642 return;
643 }
644
645 // queue metadata
646 if (result.v3_2.result.size() != 0) {
647 // Save a copy of metadata
648 batch->mResultMds[result.v3_2.partialResult].mMds.push_back(
649 std::make_pair(result.v3_2.frameNumber, result.v3_2.result));
650 }
651
652 // queue buffer
653 std::vector<int> filledStreams;
654 std::vector<V3_2::StreamBuffer> nonBatchedBuffers;
655 for (auto& buffer : result.v3_2.outputBuffers) {
656 auto it = batch->mBatchBufs.find(buffer.streamId);
657 if (it != batch->mBatchBufs.end()) {
658 InflightBatch::BufferBatch& bb = it->second;
659 pushStreamBuffer(std::move(buffer), bb.mBuffers);
660 filledStreams.push_back(buffer.streamId);
661 } else {
662 pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
663 }
664 }
665
666 // send non-batched buffers up
667 if (nonBatchedBuffers.size() > 0 || result.v3_2.inputBuffer.streamId != -1) {
668 CaptureResult nonBatchedResult;
669 nonBatchedResult.v3_2.frameNumber = result.v3_2.frameNumber;
670 nonBatchedResult.v3_2.fmqResultSize = 0;
671 nonBatchedResult.v3_2.outputBuffers.resize(nonBatchedBuffers.size());
672 for (size_t i = 0; i < nonBatchedBuffers.size(); i++) {
673 moveStreamBuffer(
674 std::move(nonBatchedBuffers[i]), nonBatchedResult.v3_2.outputBuffers[i]);
675 }
676 moveStreamBuffer(std::move(result.v3_2.inputBuffer), nonBatchedResult.v3_2.inputBuffer);
677 nonBatchedResult.v3_2.partialResult = 0; // 0 for buffer only results
678 processOneCaptureResult_3_4(nonBatchedResult);
679 }
680
681 if (result.v3_2.frameNumber == batch->mLastFrame) {
682 // Send data up
683 if (result.v3_2.partialResult > 0) {
684 sendBatchMetadataLocked(batch, result.v3_2.partialResult);
685 }
686 // send buffer up
687 if (filledStreams.size() > 0) {
688 sendBatchBuffersLocked(batch, filledStreams);
689 }
690 }
691 } // end of batch lock scope
692
693 // see if the batch is complete
694 if (result.v3_2.frameNumber == batch->mLastFrame) {
695 checkAndRemoveFirstBatch();
696 }
697}
698
699void CameraDeviceSession::ResultBatcher_3_4::processOneCaptureResult_3_4(CaptureResult& result) {
700 hidl_vec<CaptureResult> results;
701 results.resize(1);
702 results[0] = std::move(result);
703 invokeProcessCaptureResultCallback_3_4(results, /* tryWriteFmq */true);
704 freeReleaseFences_3_4(results);
705 return;
706}
707
708void CameraDeviceSession::ResultBatcher_3_4::invokeProcessCaptureResultCallback_3_4(
709 hidl_vec<CaptureResult> &results, bool tryWriteFmq) {
710 if (mProcessCaptureResultLock.tryLock() != OK) {
711 ALOGV("%s: previous call is not finished! waiting 1s...", __FUNCTION__);
712 if (mProcessCaptureResultLock.timedLock(1000000000 /* 1s */) != OK) {
713 ALOGE("%s: cannot acquire lock in 1s, cannot proceed",
714 __FUNCTION__);
715 return;
716 }
717 }
718 if (tryWriteFmq && mResultMetadataQueue->availableToWrite() > 0) {
719 for (CaptureResult &result : results) {
720 if (result.v3_2.result.size() > 0) {
721 if (mResultMetadataQueue->write(result.v3_2.result.data(),
722 result.v3_2.result.size())) {
723 result.v3_2.fmqResultSize = result.v3_2.result.size();
724 result.v3_2.result.resize(0);
725 } else {
726 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
727 result.v3_2.fmqResultSize = 0;
728 }
729 }
730
731 for (auto& onePhysMetadata : result.physicalCameraMetadata) {
732 if (mResultMetadataQueue->write(onePhysMetadata.metadata.data(),
733 onePhysMetadata.metadata.size())) {
734 onePhysMetadata.fmqMetadataSize = onePhysMetadata.metadata.size();
735 onePhysMetadata.metadata.resize(0);
736 } else {
737 ALOGW("%s: couldn't utilize fmq, fall back to hwbinder", __FUNCTION__);
738 onePhysMetadata.fmqMetadataSize = 0;
739 }
740 }
741 }
742 }
743 mCallback_3_4->processCaptureResult_3_4(results);
744 mProcessCaptureResultLock.unlock();
745}
746
747void CameraDeviceSession::ResultBatcher_3_4::freeReleaseFences_3_4(hidl_vec<CaptureResult>& results) {
748 for (auto& result : results) {
749 if (result.v3_2.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
750 native_handle_t* handle = const_cast<native_handle_t*>(
751 result.v3_2.inputBuffer.releaseFence.getNativeHandle());
752 native_handle_close(handle);
753 native_handle_delete(handle);
754 }
755 for (auto& buf : result.v3_2.outputBuffers) {
756 if (buf.releaseFence.getNativeHandle() != nullptr) {
757 native_handle_t* handle = const_cast<native_handle_t*>(
758 buf.releaseFence.getNativeHandle());
759 native_handle_close(handle);
760 native_handle_delete(handle);
761 }
762 }
763 }
764 return;
765}
766
Emilian Peeve18057b2017-11-13 16:03:44 +0000767} // namespace implementation
768} // namespace V3_4
769} // namespace device
770} // namespace camera
771} // namespace hardware
772} // namespace android