blob: c8d33ebca9ccb27ef81e67b65f942d7a792deac5 [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) :
37 V3_3::implementation::CameraDeviceSession(device, deviceInfo, callback) {
38}
39
40CameraDeviceSession::~CameraDeviceSession() {
41}
42
43Return<void> CameraDeviceSession::configureStreams_3_4(
Shuzhen Wang82e36b32017-11-28 17:00:43 -080044 const StreamConfiguration& requestedConfiguration,
45 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
Emilian Peeve18057b2017-11-13 16:03:44 +000046 Status status = initStatus();
47 HalStreamConfiguration outStreams;
48
49 // hold the inflight lock for entire configureStreams scope since there must not be any
50 // inflight request/results during stream configuration.
51 Mutex::Autolock _l(mInflightLock);
52 if (!mInflightBuffers.empty()) {
53 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
54 __FUNCTION__, mInflightBuffers.size());
55 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
56 return Void();
57 }
58
59 if (!mInflightAETriggerOverrides.empty()) {
60 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
61 " trigger overrides!", __FUNCTION__,
62 mInflightAETriggerOverrides.size());
63 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
64 return Void();
65 }
66
67 if (!mInflightRawBoostPresent.empty()) {
68 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
69 " boost overrides!", __FUNCTION__,
70 mInflightRawBoostPresent.size());
71 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
72 return Void();
73 }
74
75 if (status != Status::OK) {
76 _hidl_cb(status, outStreams);
77 return Void();
78 }
79
80 const camera_metadata_t *paramBuffer = nullptr;
81 if (0 < requestedConfiguration.sessionParams.size()) {
82 ::android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams;
83 V3_2::implementation::convertFromHidl(requestedConfiguration.sessionParams, &paramBuffer);
84 }
85
86 camera3_stream_configuration_t stream_list{};
87 hidl_vec<camera3_stream_t*> streams;
88 stream_list.session_parameters = paramBuffer;
Shuzhen Wang82e36b32017-11-28 17:00:43 -080089 if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
Emilian Peeve18057b2017-11-13 16:03:44 +000090 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
91 return Void();
92 }
93
94 ATRACE_BEGIN("camera3->configure_streams");
95 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
96 ATRACE_END();
97
98 // In case Hal returns error most likely it was not able to release
99 // the corresponding resources of the deleted streams.
100 if (ret == OK) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800101 postProcessConfigurationLocked_3_4(requestedConfiguration);
Emilian Peeve18057b2017-11-13 16:03:44 +0000102 }
103
104 if (ret == -EINVAL) {
105 status = Status::ILLEGAL_ARGUMENT;
106 } else if (ret != OK) {
107 status = Status::INTERNAL_ERROR;
108 } else {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800109 V3_4::implementation::convertToHidl(stream_list, &outStreams);
Emilian Peeve18057b2017-11-13 16:03:44 +0000110 mFirstRequest = true;
111 }
112
113 _hidl_cb(status, outStreams);
114 return Void();
115}
116
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800117bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
118 const StreamConfiguration& requestedConfiguration,
119 camera3_stream_configuration_t *stream_list /*out*/,
120 hidl_vec<camera3_stream_t*> *streams /*out*/) {
121
122 if ((stream_list == nullptr) || (streams == nullptr)) {
123 return false;
124 }
125
126 stream_list->operation_mode = (uint32_t) requestedConfiguration.operationMode;
127 stream_list->num_streams = requestedConfiguration.streams.size();
128 streams->resize(stream_list->num_streams);
129 stream_list->streams = streams->data();
130
131 for (uint32_t i = 0; i < stream_list->num_streams; i++) {
132 int id = requestedConfiguration.streams[i].v3_2.id;
133
134 if (mStreamMap.count(id) == 0) {
135 Camera3Stream stream;
136 convertFromHidl(requestedConfiguration.streams[i], &stream);
137 mStreamMap[id] = stream;
138 mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId;
139 mStreamMap[id].data_space = mapToLegacyDataspace(
140 mStreamMap[id].data_space);
141 mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
142 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
143 } else {
144 // width/height/format must not change, but usage/rotation might need to change
145 if (mStreamMap[id].stream_type !=
146 (int) requestedConfiguration.streams[i].v3_2.streamType ||
147 mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width ||
148 mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height ||
149 mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
150 mStreamMap[id].data_space !=
151 mapToLegacyDataspace( static_cast<android_dataspace_t> (
152 requestedConfiguration.streams[i].v3_2.dataSpace)) ||
153 mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) {
154 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
155 return false;
156 }
157 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
158 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
159 }
160 (*streams)[i] = &mStreamMap[id];
161 }
162
163 return true;
164}
165
166void CameraDeviceSession::postProcessConfigurationLocked_3_4(
167 const StreamConfiguration& requestedConfiguration) {
168 // delete unused streams, note we do this after adding new streams to ensure new stream
169 // will not have the same address as deleted stream, and HAL has a chance to reference
170 // the to be deleted stream in configure_streams call
171 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
172 int id = it->first;
173 bool found = false;
174 for (const auto& stream : requestedConfiguration.streams) {
175 if (id == stream.v3_2.id) {
176 found = true;
177 break;
178 }
179 }
180 if (!found) {
181 // Unmap all buffers of deleted stream
182 // in case the configuration call succeeds and HAL
183 // is able to release the corresponding resources too.
184 cleanupBuffersLocked(id);
185 it = mStreamMap.erase(it);
186 } else {
187 ++it;
188 }
189 }
190
191 // Track video streams
192 mVideoStreamIds.clear();
193 for (const auto& stream : requestedConfiguration.streams) {
194 if (stream.v3_2.streamType == StreamType::OUTPUT &&
195 stream.v3_2.usage &
196 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
197 mVideoStreamIds.push_back(stream.v3_2.id);
198 }
199 }
200 mResultBatcher.setBatchedStreams(mVideoStreamIds);
201}
202
203Return<void> CameraDeviceSession::processCaptureRequest_3_4(
Emilian Peevb75aa352018-01-17 11:00:54 +0000204 const hidl_vec<V3_4::CaptureRequest>& requests,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800205 const hidl_vec<V3_2::BufferCache>& cachesToRemove,
Emilian Peevb75aa352018-01-17 11:00:54 +0000206 ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800207 updateBufferCaches(cachesToRemove);
208
209 uint32_t numRequestProcessed = 0;
210 Status s = Status::OK;
211 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
212 s = processOneCaptureRequest_3_4(requests[i]);
213 if (s != Status::OK) {
214 break;
215 }
216 }
217
218 if (s == Status::OK && requests.size() > 1) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000219 mResultBatcher.registerBatch(requests[0].v3_2.frameNumber, requests.size());
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800220 }
221
222 _hidl_cb(s, numRequestProcessed);
223 return Void();
224}
225
Emilian Peevb75aa352018-01-17 11:00:54 +0000226Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800227 Status status = initStatus();
228 if (status != Status::OK) {
229 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
230 return status;
231 }
232
233 camera3_capture_request_t halRequest;
Emilian Peevb75aa352018-01-17 11:00:54 +0000234 halRequest.frame_number = request.v3_2.frameNumber;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800235
236 bool converted = true;
237 V3_2::CameraMetadata settingsFmq; // settings from FMQ
Emilian Peevb75aa352018-01-17 11:00:54 +0000238 if (request.v3_2.fmqSettingsSize > 0) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800239 // non-blocking read; client must write metadata before calling
240 // processOneCaptureRequest
Emilian Peevb75aa352018-01-17 11:00:54 +0000241 settingsFmq.resize(request.v3_2.fmqSettingsSize);
242 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.v3_2.fmqSettingsSize);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800243 if (read) {
244 converted = V3_2::implementation::convertFromHidl(settingsFmq, &halRequest.settings);
245 } else {
246 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
247 converted = false;
248 }
249 } else {
Emilian Peevb75aa352018-01-17 11:00:54 +0000250 converted = V3_2::implementation::convertFromHidl(request.v3_2.settings,
251 &halRequest.settings);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800252 }
253
254 if (!converted) {
255 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
256 return Status::ILLEGAL_ARGUMENT;
257 }
258
259 if (mFirstRequest && halRequest.settings == nullptr) {
260 ALOGE("%s: capture request settings must not be null for first request!",
261 __FUNCTION__);
262 return Status::ILLEGAL_ARGUMENT;
263 }
264
265 hidl_vec<buffer_handle_t*> allBufPtrs;
266 hidl_vec<int> allFences;
Emilian Peevb75aa352018-01-17 11:00:54 +0000267 bool hasInputBuf = (request.v3_2.inputBuffer.streamId != -1 &&
268 request.v3_2.inputBuffer.bufferId != 0);
269 size_t numOutputBufs = request.v3_2.outputBuffers.size();
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800270 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
271
272 if (numOutputBufs == 0) {
273 ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
274 return Status::ILLEGAL_ARGUMENT;
275 }
276
Emilian Peevb75aa352018-01-17 11:00:54 +0000277 status = importRequest(request.v3_2, allBufPtrs, allFences);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800278 if (status != Status::OK) {
279 return status;
280 }
281
282 hidl_vec<camera3_stream_buffer_t> outHalBufs;
283 outHalBufs.resize(numOutputBufs);
284 bool aeCancelTriggerNeeded = false;
285 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
286 {
287 Mutex::Autolock _l(mInflightLock);
288 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000289 auto streamId = request.v3_2.inputBuffer.streamId;
290 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800291 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
292 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000293 allBufPtrs[numOutputBufs], request.v3_2.inputBuffer.status,
294 &mStreamMap[request.v3_2.inputBuffer.streamId], allFences[numOutputBufs],
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800295 &bufCache);
296 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
297 halRequest.input_buffer = &bufCache;
298 } else {
299 halRequest.input_buffer = nullptr;
300 }
301
302 halRequest.num_output_buffers = numOutputBufs;
303 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000304 auto streamId = request.v3_2.outputBuffers[i].streamId;
305 auto key = std::make_pair(streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800306 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
307 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000308 allBufPtrs[i], request.v3_2.outputBuffers[i].status,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800309 &mStreamMap[streamId], allFences[i],
310 &bufCache);
311 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
312 outHalBufs[i] = bufCache;
313 }
314 halRequest.output_buffers = outHalBufs.data();
315
316 AETriggerCancelOverride triggerOverride;
317 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
318 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
319 if (aeCancelTriggerNeeded) {
320 mInflightAETriggerOverrides[halRequest.frame_number] =
321 triggerOverride;
322 halRequest.settings = settingsOverride.getAndLock();
323 }
324 }
325
Emilian Peevb75aa352018-01-17 11:00:54 +0000326 std::vector<const char *> physicalCameraIds;
327 std::vector<const camera_metadata_t *> physicalCameraSettings;
328 std::vector<V3_2::CameraMetadata> physicalFmq;
329 size_t settingsCount = request.physicalCameraSettings.size();
330 if (settingsCount > 0) {
331 physicalCameraIds.reserve(settingsCount);
332 physicalCameraSettings.reserve(settingsCount);
333 physicalFmq.reserve(settingsCount);
334
335 for (size_t i = 0; i < settingsCount; i++) {
336 uint64_t settingsSize = request.physicalCameraSettings[i].fmqSettingsSize;
337 const camera_metadata_t *settings;
338 if (settingsSize > 0) {
339 physicalFmq.push_back(V3_2::CameraMetadata(settingsSize));
340 bool read = mRequestMetadataQueue->read(physicalFmq[i].data(), settingsSize);
341 if (read) {
342 converted = V3_2::implementation::convertFromHidl(physicalFmq[i], &settings);
343 physicalCameraSettings.push_back(settings);
344 } else {
345 ALOGE("%s: physical camera settings metadata couldn't be read from fmq!",
346 __FUNCTION__);
347 converted = false;
348 }
349 } else {
350 converted = V3_2::implementation::convertFromHidl(
351 request.physicalCameraSettings[i].settings, &settings);
352 physicalCameraSettings.push_back(settings);
353 }
354
355 if (!converted) {
356 ALOGE("%s: physical camera settings metadata is corrupt!", __FUNCTION__);
357 return Status::ILLEGAL_ARGUMENT;
358 }
359 physicalCameraIds.push_back(request.physicalCameraSettings[i].physicalCameraId.c_str());
360 }
361 }
362 halRequest.num_physcam_settings = settingsCount;
363 halRequest.physcam_id = physicalCameraIds.data();
364 halRequest.physcam_settings = physicalCameraSettings.data();
365
366 ATRACE_ASYNC_BEGIN("frame capture", request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800367 ATRACE_BEGIN("camera3->process_capture_request");
368 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
369 ATRACE_END();
370 if (aeCancelTriggerNeeded) {
371 settingsOverride.unlock(halRequest.settings);
372 }
373 if (ret != OK) {
374 Mutex::Autolock _l(mInflightLock);
375 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
376
377 cleanupInflightFences(allFences, numBufs);
378 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000379 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800380 mInflightBuffers.erase(key);
381 }
382 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000383 auto key = std::make_pair(request.v3_2.outputBuffers[i].streamId,
384 request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800385 mInflightBuffers.erase(key);
386 }
387 if (aeCancelTriggerNeeded) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000388 mInflightAETriggerOverrides.erase(request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800389 }
Emilian Peevb75aa352018-01-17 11:00:54 +0000390
391 if (ret == BAD_VALUE) {
392 return Status::ILLEGAL_ARGUMENT;
393 } else {
394 return Status::INTERNAL_ERROR;
395 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800396 }
397
398 mFirstRequest = false;
399 return Status::OK;
400}
401
Emilian Peeve18057b2017-11-13 16:03:44 +0000402} // namespace implementation
403} // namespace V3_4
404} // namespace device
405} // namespace camera
406} // namespace hardware
407} // namespace android