blob: d0547882c2ff2a6249e21915f7f07c33734be011 [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
Eino-Ville Talvala658d30d2018-01-18 12:55:07 -080043Return<void> CameraDeviceSession::constructDefaultRequestSettings_3_4(
44 RequestTemplate type, ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) {
45 V3_2::CameraMetadata outMetadata;
46 Status status = constructDefaultRequestSettingsRaw( (int) type, &outMetadata);
47 _hidl_cb(status, outMetadata);
48 return Void();
49}
50
Emilian Peeve18057b2017-11-13 16:03:44 +000051Return<void> CameraDeviceSession::configureStreams_3_4(
Shuzhen Wang82e36b32017-11-28 17:00:43 -080052 const StreamConfiguration& requestedConfiguration,
53 ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
Emilian Peeve18057b2017-11-13 16:03:44 +000054 Status status = initStatus();
55 HalStreamConfiguration outStreams;
56
57 // hold the inflight lock for entire configureStreams scope since there must not be any
58 // inflight request/results during stream configuration.
59 Mutex::Autolock _l(mInflightLock);
60 if (!mInflightBuffers.empty()) {
61 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
62 __FUNCTION__, mInflightBuffers.size());
63 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
64 return Void();
65 }
66
67 if (!mInflightAETriggerOverrides.empty()) {
68 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
69 " trigger overrides!", __FUNCTION__,
70 mInflightAETriggerOverrides.size());
71 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
72 return Void();
73 }
74
75 if (!mInflightRawBoostPresent.empty()) {
76 ALOGE("%s: trying to configureStreams while there are still %zu inflight"
77 " boost overrides!", __FUNCTION__,
78 mInflightRawBoostPresent.size());
79 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
80 return Void();
81 }
82
83 if (status != Status::OK) {
84 _hidl_cb(status, outStreams);
85 return Void();
86 }
87
88 const camera_metadata_t *paramBuffer = nullptr;
89 if (0 < requestedConfiguration.sessionParams.size()) {
90 ::android::hardware::camera::common::V1_0::helper::CameraMetadata sessionParams;
91 V3_2::implementation::convertFromHidl(requestedConfiguration.sessionParams, &paramBuffer);
92 }
93
94 camera3_stream_configuration_t stream_list{};
95 hidl_vec<camera3_stream_t*> streams;
96 stream_list.session_parameters = paramBuffer;
Shuzhen Wang82e36b32017-11-28 17:00:43 -080097 if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
Emilian Peeve18057b2017-11-13 16:03:44 +000098 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
99 return Void();
100 }
101
102 ATRACE_BEGIN("camera3->configure_streams");
103 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
104 ATRACE_END();
105
106 // In case Hal returns error most likely it was not able to release
107 // the corresponding resources of the deleted streams.
108 if (ret == OK) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800109 postProcessConfigurationLocked_3_4(requestedConfiguration);
Emilian Peeve18057b2017-11-13 16:03:44 +0000110 }
111
112 if (ret == -EINVAL) {
113 status = Status::ILLEGAL_ARGUMENT;
114 } else if (ret != OK) {
115 status = Status::INTERNAL_ERROR;
116 } else {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800117 V3_4::implementation::convertToHidl(stream_list, &outStreams);
Emilian Peeve18057b2017-11-13 16:03:44 +0000118 mFirstRequest = true;
119 }
120
121 _hidl_cb(status, outStreams);
122 return Void();
123}
124
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800125bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
126 const StreamConfiguration& requestedConfiguration,
127 camera3_stream_configuration_t *stream_list /*out*/,
128 hidl_vec<camera3_stream_t*> *streams /*out*/) {
129
130 if ((stream_list == nullptr) || (streams == nullptr)) {
131 return false;
132 }
133
134 stream_list->operation_mode = (uint32_t) requestedConfiguration.operationMode;
135 stream_list->num_streams = requestedConfiguration.streams.size();
136 streams->resize(stream_list->num_streams);
137 stream_list->streams = streams->data();
138
139 for (uint32_t i = 0; i < stream_list->num_streams; i++) {
140 int id = requestedConfiguration.streams[i].v3_2.id;
141
142 if (mStreamMap.count(id) == 0) {
143 Camera3Stream stream;
144 convertFromHidl(requestedConfiguration.streams[i], &stream);
145 mStreamMap[id] = stream;
146 mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId;
147 mStreamMap[id].data_space = mapToLegacyDataspace(
148 mStreamMap[id].data_space);
149 mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
150 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
151 } else {
152 // width/height/format must not change, but usage/rotation might need to change
153 if (mStreamMap[id].stream_type !=
154 (int) requestedConfiguration.streams[i].v3_2.streamType ||
155 mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width ||
156 mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height ||
157 mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
158 mStreamMap[id].data_space !=
159 mapToLegacyDataspace( static_cast<android_dataspace_t> (
160 requestedConfiguration.streams[i].v3_2.dataSpace)) ||
161 mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) {
162 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
163 return false;
164 }
165 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
166 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
167 }
168 (*streams)[i] = &mStreamMap[id];
169 }
170
171 return true;
172}
173
174void CameraDeviceSession::postProcessConfigurationLocked_3_4(
175 const StreamConfiguration& requestedConfiguration) {
176 // delete unused streams, note we do this after adding new streams to ensure new stream
177 // will not have the same address as deleted stream, and HAL has a chance to reference
178 // the to be deleted stream in configure_streams call
179 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
180 int id = it->first;
181 bool found = false;
182 for (const auto& stream : requestedConfiguration.streams) {
183 if (id == stream.v3_2.id) {
184 found = true;
185 break;
186 }
187 }
188 if (!found) {
189 // Unmap all buffers of deleted stream
190 // in case the configuration call succeeds and HAL
191 // is able to release the corresponding resources too.
192 cleanupBuffersLocked(id);
193 it = mStreamMap.erase(it);
194 } else {
195 ++it;
196 }
197 }
198
199 // Track video streams
200 mVideoStreamIds.clear();
201 for (const auto& stream : requestedConfiguration.streams) {
202 if (stream.v3_2.streamType == StreamType::OUTPUT &&
203 stream.v3_2.usage &
204 graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
205 mVideoStreamIds.push_back(stream.v3_2.id);
206 }
207 }
208 mResultBatcher.setBatchedStreams(mVideoStreamIds);
209}
210
211Return<void> CameraDeviceSession::processCaptureRequest_3_4(
Emilian Peevb75aa352018-01-17 11:00:54 +0000212 const hidl_vec<V3_4::CaptureRequest>& requests,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800213 const hidl_vec<V3_2::BufferCache>& cachesToRemove,
Emilian Peevb75aa352018-01-17 11:00:54 +0000214 ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800215 updateBufferCaches(cachesToRemove);
216
217 uint32_t numRequestProcessed = 0;
218 Status s = Status::OK;
219 for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
220 s = processOneCaptureRequest_3_4(requests[i]);
221 if (s != Status::OK) {
222 break;
223 }
224 }
225
226 if (s == Status::OK && requests.size() > 1) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000227 mResultBatcher.registerBatch(requests[0].v3_2.frameNumber, requests.size());
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800228 }
229
230 _hidl_cb(s, numRequestProcessed);
231 return Void();
232}
233
Emilian Peevb75aa352018-01-17 11:00:54 +0000234Status CameraDeviceSession::processOneCaptureRequest_3_4(const V3_4::CaptureRequest& request) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800235 Status status = initStatus();
236 if (status != Status::OK) {
237 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
238 return status;
239 }
240
241 camera3_capture_request_t halRequest;
Emilian Peevb75aa352018-01-17 11:00:54 +0000242 halRequest.frame_number = request.v3_2.frameNumber;
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800243
244 bool converted = true;
245 V3_2::CameraMetadata settingsFmq; // settings from FMQ
Emilian Peevb75aa352018-01-17 11:00:54 +0000246 if (request.v3_2.fmqSettingsSize > 0) {
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800247 // non-blocking read; client must write metadata before calling
248 // processOneCaptureRequest
Emilian Peevb75aa352018-01-17 11:00:54 +0000249 settingsFmq.resize(request.v3_2.fmqSettingsSize);
250 bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.v3_2.fmqSettingsSize);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800251 if (read) {
252 converted = V3_2::implementation::convertFromHidl(settingsFmq, &halRequest.settings);
253 } else {
254 ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
255 converted = false;
256 }
257 } else {
Emilian Peevb75aa352018-01-17 11:00:54 +0000258 converted = V3_2::implementation::convertFromHidl(request.v3_2.settings,
259 &halRequest.settings);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800260 }
261
262 if (!converted) {
263 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
264 return Status::ILLEGAL_ARGUMENT;
265 }
266
267 if (mFirstRequest && halRequest.settings == nullptr) {
268 ALOGE("%s: capture request settings must not be null for first request!",
269 __FUNCTION__);
270 return Status::ILLEGAL_ARGUMENT;
271 }
272
273 hidl_vec<buffer_handle_t*> allBufPtrs;
274 hidl_vec<int> allFences;
Emilian Peevb75aa352018-01-17 11:00:54 +0000275 bool hasInputBuf = (request.v3_2.inputBuffer.streamId != -1 &&
276 request.v3_2.inputBuffer.bufferId != 0);
277 size_t numOutputBufs = request.v3_2.outputBuffers.size();
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800278 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
279
280 if (numOutputBufs == 0) {
281 ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
282 return Status::ILLEGAL_ARGUMENT;
283 }
284
Emilian Peevb75aa352018-01-17 11:00:54 +0000285 status = importRequest(request.v3_2, allBufPtrs, allFences);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800286 if (status != Status::OK) {
287 return status;
288 }
289
290 hidl_vec<camera3_stream_buffer_t> outHalBufs;
291 outHalBufs.resize(numOutputBufs);
292 bool aeCancelTriggerNeeded = false;
293 ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
294 {
295 Mutex::Autolock _l(mInflightLock);
296 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000297 auto streamId = request.v3_2.inputBuffer.streamId;
298 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800299 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
300 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000301 allBufPtrs[numOutputBufs], request.v3_2.inputBuffer.status,
302 &mStreamMap[request.v3_2.inputBuffer.streamId], allFences[numOutputBufs],
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800303 &bufCache);
304 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
305 halRequest.input_buffer = &bufCache;
306 } else {
307 halRequest.input_buffer = nullptr;
308 }
309
310 halRequest.num_output_buffers = numOutputBufs;
311 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000312 auto streamId = request.v3_2.outputBuffers[i].streamId;
313 auto key = std::make_pair(streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800314 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
315 convertFromHidl(
Emilian Peevb75aa352018-01-17 11:00:54 +0000316 allBufPtrs[i], request.v3_2.outputBuffers[i].status,
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800317 &mStreamMap[streamId], allFences[i],
318 &bufCache);
319 bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
320 outHalBufs[i] = bufCache;
321 }
322 halRequest.output_buffers = outHalBufs.data();
323
324 AETriggerCancelOverride triggerOverride;
325 aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
326 halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
327 if (aeCancelTriggerNeeded) {
328 mInflightAETriggerOverrides[halRequest.frame_number] =
329 triggerOverride;
330 halRequest.settings = settingsOverride.getAndLock();
331 }
332 }
333
Emilian Peevb75aa352018-01-17 11:00:54 +0000334 std::vector<const char *> physicalCameraIds;
335 std::vector<const camera_metadata_t *> physicalCameraSettings;
336 std::vector<V3_2::CameraMetadata> physicalFmq;
337 size_t settingsCount = request.physicalCameraSettings.size();
338 if (settingsCount > 0) {
339 physicalCameraIds.reserve(settingsCount);
340 physicalCameraSettings.reserve(settingsCount);
341 physicalFmq.reserve(settingsCount);
342
343 for (size_t i = 0; i < settingsCount; i++) {
344 uint64_t settingsSize = request.physicalCameraSettings[i].fmqSettingsSize;
345 const camera_metadata_t *settings;
346 if (settingsSize > 0) {
347 physicalFmq.push_back(V3_2::CameraMetadata(settingsSize));
348 bool read = mRequestMetadataQueue->read(physicalFmq[i].data(), settingsSize);
349 if (read) {
350 converted = V3_2::implementation::convertFromHidl(physicalFmq[i], &settings);
351 physicalCameraSettings.push_back(settings);
352 } else {
353 ALOGE("%s: physical camera settings metadata couldn't be read from fmq!",
354 __FUNCTION__);
355 converted = false;
356 }
357 } else {
358 converted = V3_2::implementation::convertFromHidl(
359 request.physicalCameraSettings[i].settings, &settings);
360 physicalCameraSettings.push_back(settings);
361 }
362
363 if (!converted) {
364 ALOGE("%s: physical camera settings metadata is corrupt!", __FUNCTION__);
365 return Status::ILLEGAL_ARGUMENT;
366 }
367 physicalCameraIds.push_back(request.physicalCameraSettings[i].physicalCameraId.c_str());
368 }
369 }
370 halRequest.num_physcam_settings = settingsCount;
371 halRequest.physcam_id = physicalCameraIds.data();
372 halRequest.physcam_settings = physicalCameraSettings.data();
373
374 ATRACE_ASYNC_BEGIN("frame capture", request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800375 ATRACE_BEGIN("camera3->process_capture_request");
376 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
377 ATRACE_END();
378 if (aeCancelTriggerNeeded) {
379 settingsOverride.unlock(halRequest.settings);
380 }
381 if (ret != OK) {
382 Mutex::Autolock _l(mInflightLock);
383 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
384
385 cleanupInflightFences(allFences, numBufs);
386 if (hasInputBuf) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000387 auto key = std::make_pair(request.v3_2.inputBuffer.streamId, request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800388 mInflightBuffers.erase(key);
389 }
390 for (size_t i = 0; i < numOutputBufs; i++) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000391 auto key = std::make_pair(request.v3_2.outputBuffers[i].streamId,
392 request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800393 mInflightBuffers.erase(key);
394 }
395 if (aeCancelTriggerNeeded) {
Emilian Peevb75aa352018-01-17 11:00:54 +0000396 mInflightAETriggerOverrides.erase(request.v3_2.frameNumber);
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800397 }
Emilian Peevb75aa352018-01-17 11:00:54 +0000398
399 if (ret == BAD_VALUE) {
400 return Status::ILLEGAL_ARGUMENT;
401 } else {
402 return Status::INTERNAL_ERROR;
403 }
Shuzhen Wang82e36b32017-11-28 17:00:43 -0800404 }
405
406 mFirstRequest = false;
407 return Status::OK;
408}
409
Emilian Peeve18057b2017-11-13 16:03:44 +0000410} // namespace implementation
411} // namespace V3_4
412} // namespace device
413} // namespace camera
414} // namespace hardware
415} // namespace android