blob: 26b7b738efe49671d795bd7beff1765c9274b3d0 [file] [log] [blame]
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "CamDevSession@3.2-impl"
18#include <android/log.h>
19
20#include <utils/Trace.h>
21#include <hardware/gralloc.h>
22#include <hardware/gralloc1.h>
23#include "CameraDeviceSession.h"
24
25namespace android {
26namespace hardware {
27namespace camera {
28namespace device {
29namespace V3_2 {
30namespace implementation {
31
32namespace {
33
34// Copy pasted from Hwc.cpp. Use this until gralloc mapper HAL is working
35class HandleImporter {
36public:
37 HandleImporter() : mInitialized(false) {}
38
39 bool initialize()
40 {
41 // allow only one client
42 if (mInitialized) {
43 return false;
44 }
45
46 if (!openGralloc()) {
47 return false;
48 }
49
50 mInitialized = true;
51 return true;
52 }
53
54 void cleanup()
55 {
56 if (!mInitialized) {
57 return;
58 }
59
60 closeGralloc();
61 mInitialized = false;
62 }
63
64 // In IComposer, any buffer_handle_t is owned by the caller and we need to
65 // make a clone for hwcomposer2. We also need to translate empty handle
66 // to nullptr. This function does that, in-place.
67 bool importBuffer(buffer_handle_t& handle)
68 {
69 if (!handle->numFds && !handle->numInts) {
70 handle = nullptr;
71 return true;
72 }
73
74 buffer_handle_t clone = cloneBuffer(handle);
75 if (!clone) {
76 return false;
77 }
78
79 handle = clone;
80 return true;
81 }
82
83 void freeBuffer(buffer_handle_t handle)
84 {
85 if (!handle) {
86 return;
87 }
88
89 releaseBuffer(handle);
90 }
91
92 bool importFence(const native_handle_t* handle, int& fd)
93 {
94 if (handle == nullptr || handle->numFds == 0) {
95 fd = -1;
96 } else if (handle->numFds == 1) {
97 fd = dup(handle->data[0]);
98 if (fd < 0) {
99 ALOGE("failed to dup fence fd %d", handle->data[0]);
100 return false;
101 }
102 } else {
103 ALOGE("invalid fence handle with %d file descriptors",
104 handle->numFds);
105 return false;
106 }
107
108 return true;
109 }
110
111 void closeFence(int fd)
112 {
113 if (fd >= 0) {
114 close(fd);
115 }
116 }
117
118private:
119 bool mInitialized;
120
121 // Some existing gralloc drivers do not support retaining more than once,
122 // when we are in passthrough mode.
123#ifdef BINDERIZED
124 bool openGralloc()
125 {
126 const hw_module_t* module;
127 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
128 if (err) {
129 ALOGE("failed to get gralloc module");
130 return false;
131 }
132
133 uint8_t major = (module->module_api_version >> 8) & 0xff;
134 if (major > 1) {
135 ALOGE("unknown gralloc module major version %d", major);
136 return false;
137 }
138
139 if (major == 1) {
140 err = gralloc1_open(module, &mDevice);
141 if (err) {
142 ALOGE("failed to open gralloc1 device");
143 return false;
144 }
145
146 mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
147 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
148 mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
149 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
150 if (!mRetain || !mRelease) {
151 ALOGE("invalid gralloc1 device");
152 gralloc1_close(mDevice);
153 return false;
154 }
155 } else {
156 mModule = reinterpret_cast<const gralloc_module_t*>(module);
157 }
158
159 return true;
160 }
161
162 void closeGralloc()
163 {
164 if (mDevice) {
165 gralloc1_close(mDevice);
166 }
167 }
168
169 buffer_handle_t cloneBuffer(buffer_handle_t handle)
170 {
171 native_handle_t* clone = native_handle_clone(handle);
172 if (!clone) {
173 ALOGE("failed to clone buffer %p", handle);
174 return nullptr;
175 }
176
177 bool err;
178 if (mDevice) {
179 err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
180 } else {
181 err = (mModule->registerBuffer(mModule, clone) != 0);
182 }
183
184 if (err) {
185 ALOGE("failed to retain/register buffer %p", clone);
186 native_handle_close(clone);
187 native_handle_delete(clone);
188 return nullptr;
189 }
190
191 return clone;
192 }
193
194 void releaseBuffer(buffer_handle_t handle)
195 {
196 if (mDevice) {
197 mRelease(mDevice, handle);
198 } else {
199 mModule->unregisterBuffer(mModule, handle);
200 native_handle_close(handle);
201 native_handle_delete(const_cast<native_handle_t*>(handle));
202 }
203 }
204
205 // gralloc1
206 gralloc1_device_t* mDevice;
207 GRALLOC1_PFN_RETAIN mRetain;
208 GRALLOC1_PFN_RELEASE mRelease;
209
210 // gralloc0
211 const gralloc_module_t* mModule;
212#else
213 bool openGralloc() { return true; }
214 void closeGralloc() {}
215 buffer_handle_t cloneBuffer(buffer_handle_t handle) { return handle; }
216 void releaseBuffer(buffer_handle_t) {}
217#endif
218};
219
220HandleImporter sHandleImporter;
221
222} // Anonymous namespace
223
224CameraDeviceSession::CameraDeviceSession(
225 camera3_device_t* device, const sp<ICameraDeviceCallback>& callback) :
226 camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
227 mDevice(device),
228 mCallback(callback) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700229 // For now, we init sHandleImporter but do not cleanup (keep it alive until
230 // HAL process ends)
231 sHandleImporter.initialize();
232
233 mInitFail = initialize();
234}
235
236bool CameraDeviceSession::initialize() {
237 /** Initialize device with callback functions */
238 ATRACE_BEGIN("camera3->initialize");
239 status_t res = mDevice->ops->initialize(mDevice, this);
240 ATRACE_END();
241
242 if (res != OK) {
243 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
244 __FUNCTION__, strerror(-res), res);
245 mDevice->common.close(&mDevice->common);
246 mClosed = true;
247 return true;
248 }
249 return false;
250}
251
252CameraDeviceSession::~CameraDeviceSession() {
253 if (!isClosed()) {
254 ALOGE("CameraDeviceSession deleted before close!");
255 close();
256 }
257}
258
259bool CameraDeviceSession::isClosed() {
260 Mutex::Autolock _l(mStateLock);
261 return mClosed;
262}
263
264Status CameraDeviceSession::initStatus() const {
265 Mutex::Autolock _l(mStateLock);
266 Status status = Status::OK;
267 if (mInitFail) {
268 status = Status::INTERNAL_ERROR;
269 } else if (mDisconnected) {
270 status = Status::CAMERA_DISCONNECTED;
271 } else if (mClosed) {
272 status = Status::INTERNAL_ERROR;
273 }
274 return status;
275}
276
277void CameraDeviceSession::disconnect() {
278 Mutex::Autolock _l(mStateLock);
279 mDisconnected = true;
280 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
281 if (!mClosed) {
282 mDevice->common.close(&mDevice->common);
283 mClosed = true;
284 }
285}
286
287void CameraDeviceSession::dumpState(const native_handle_t* fd) {
288 if (!isClosed()) {
289 mDevice->ops->dump(mDevice, fd->data[0]);
290 }
291}
292
293Status CameraDeviceSession::importRequest(
294 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800295 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700296 hidl_vec<int>& allFences) {
297 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800298 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700299 size_t numOutputBufs = request.outputBuffers.size();
300 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
301 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800302 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800303 hidl_vec<uint64_t> allBufIds;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700304 allBufs.resize(numBufs);
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800305 allBufIds.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800306 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700307 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800308 std::vector<int32_t> streamIds(numBufs);
309
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700310 for (size_t i = 0; i < numOutputBufs; i++) {
311 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800312 allBufIds[i] = request.outputBuffers[i].bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800313 allBufPtrs[i] = &allBufs[i];
314 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700315 }
316 if (hasInputBuf) {
317 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800318 allBufIds[numOutputBufs] = request.inputBuffer.bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800319 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
320 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700321 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800322
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700323 for (size_t i = 0; i < numBufs; i++) {
324 buffer_handle_t buf = allBufs[i];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800325 uint64_t bufId = allBufIds[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800326 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800327 if (cbs.count(bufId) == 0) {
328 if (buf == nullptr) {
329 ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
330 return Status::ILLEGAL_ARGUMENT;
331 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800332 // Register a newly seen buffer
333 buffer_handle_t importedBuf = buf;
334 sHandleImporter.importBuffer(importedBuf);
335 if (importedBuf == nullptr) {
336 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
337 return Status::INTERNAL_ERROR;
338 } else {
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800339 cbs[bufId] = importedBuf;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800340 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700341 }
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800342 allBufPtrs[i] = &cbs[bufId];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700343 }
344
345 // All buffers are imported. Now validate output buffer acquire fences
346 for (size_t i = 0; i < numOutputBufs; i++) {
347 if (!sHandleImporter.importFence(
348 request.outputBuffers[i].acquireFence, allFences[i])) {
349 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800350 cleanupInflightFences(allFences, i);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700351 return Status::INTERNAL_ERROR;
352 }
353 }
354
355 // Validate input buffer acquire fences
356 if (hasInputBuf) {
357 if (!sHandleImporter.importFence(
358 request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
359 ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800360 cleanupInflightFences(allFences, numOutputBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700361 return Status::INTERNAL_ERROR;
362 }
363 }
364 return Status::OK;
365}
366
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800367void CameraDeviceSession::cleanupInflightFences(
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700368 hidl_vec<int>& allFences, size_t numFences) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700369 for (size_t j = 0; j < numFences; j++) {
370 sHandleImporter.closeFence(allFences[j]);
371 }
372}
373
374// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
375Return<void> CameraDeviceSession::constructDefaultRequestSettings(
376 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
377 Status status = initStatus();
378 CameraMetadata outMetadata;
379 const camera_metadata_t *rawRequest;
380 if (status == Status::OK) {
381 ATRACE_BEGIN("camera3->construct_default_request_settings");
382 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
383 ATRACE_END();
384 if (rawRequest == nullptr) {
385 ALOGI("%s: template %d is not supported on this camera device",
386 __FUNCTION__, type);
387 status = Status::ILLEGAL_ARGUMENT;
388 } else {
389 convertToHidl(rawRequest, &outMetadata);
390 }
391 }
392 _hidl_cb(status, outMetadata);
393 return Void();
394}
395
396Return<void> CameraDeviceSession::configureStreams(
397 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
398 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800399 HalStreamConfiguration outStreams;
400
401 // hold the inflight lock for entire configureStreams scope since there must not be any
402 // inflight request/results during stream configuration.
403 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700404 if (!mInflightBuffers.empty()) {
405 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
406 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800407 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
408 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700409 }
410
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800411
412
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700413 if (status == Status::OK) {
414 camera3_stream_configuration_t stream_list;
415 hidl_vec<camera3_stream_t*> streams;
416
417 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
418 stream_list.num_streams = requestedConfiguration.streams.size();
419 streams.resize(stream_list.num_streams);
420 stream_list.streams = streams.data();
421
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700422 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800423 int id = requestedConfiguration.streams[i].id;
424
425 if (mStreamMap.count(id) == 0) {
426 Camera3Stream stream;
427 convertFromHidl(requestedConfiguration.streams[i], &stream);
428 mStreamMap[id] = stream;
429 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
430 } else {
431 // width/height/format must not change, but usage/rotation might need to change
432 if (mStreamMap[id].stream_type !=
433 (int) requestedConfiguration.streams[i].streamType ||
434 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
435 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
436 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
437 mStreamMap[id].data_space != (android_dataspace_t)
438 requestedConfiguration.streams[i].dataSpace) {
439 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
440 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
441 return Void();
442 }
443 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
444 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
445 }
446 streams[i] = &mStreamMap[id];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700447 }
448
449 ATRACE_BEGIN("camera3->configure_streams");
450 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
451 ATRACE_END();
452
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800453 // delete unused streams, note we do this after adding new streams to ensure new stream
454 // will not have the same address as deleted stream, and HAL has a chance to reference
455 // the to be deleted stream in configure_streams call
456 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
457 int id = it->first;
458 bool found = false;
459 for (const auto& stream : requestedConfiguration.streams) {
460 if (id == stream.id) {
461 found = true;
462 break;
463 }
464 }
465 if (!found) {
466 // Unmap all buffers of deleted stream
467 for (auto& pair : mCirculatingBuffers.at(id)) {
468 sHandleImporter.freeBuffer(pair.second);
469 }
470 mCirculatingBuffers[id].clear();
471 mCirculatingBuffers.erase(id);
472 it = mStreamMap.erase(it);
473 } else {
474 ++it;
475 }
476 }
477
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700478 if (ret == -EINVAL) {
479 status = Status::ILLEGAL_ARGUMENT;
480 } else if (ret != OK) {
481 status = Status::INTERNAL_ERROR;
482 } else {
483 convertToHidl(stream_list, &outStreams);
484 }
485
486 }
487 _hidl_cb(status, outStreams);
488 return Void();
489}
490
491Return<Status> CameraDeviceSession::processCaptureRequest(const CaptureRequest& request) {
492 Status status = initStatus();
493 if (status != Status::OK) {
494 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
495 return status;
496 }
497
498 camera3_capture_request_t halRequest;
499 halRequest.frame_number = request.frameNumber;
500 bool converted = convertFromHidl(request.settings, &halRequest.settings);
501 if (!converted) {
502 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
503 return Status::INTERNAL_ERROR;
504 }
505
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800506 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700507 hidl_vec<int> allFences;
508 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800509 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700510 size_t numOutputBufs = request.outputBuffers.size();
511 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800512 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700513 if (status != Status::OK) {
514 return status;
515 }
516
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700517 hidl_vec<camera3_stream_buffer_t> outHalBufs;
518 outHalBufs.resize(numOutputBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800519 {
520 Mutex::Autolock _l(mInflightLock);
521 if (hasInputBuf) {
522 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
523 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
524 convertFromHidl(
525 allBufPtrs[numOutputBufs], request.inputBuffer.status,
526 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
527 &bufCache);
528 halRequest.input_buffer = &bufCache;
529 } else {
530 halRequest.input_buffer = nullptr;
531 }
532
533 halRequest.num_output_buffers = numOutputBufs;
534 for (size_t i = 0; i < numOutputBufs; i++) {
535 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
536 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
537 convertFromHidl(
538 allBufPtrs[i], request.outputBuffers[i].status,
539 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
540 &bufCache);
541 outHalBufs[i] = bufCache;
542 }
543 halRequest.output_buffers = outHalBufs.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700544 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700545
546 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
547 ATRACE_BEGIN("camera3->process_capture_request");
548 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
549 ATRACE_END();
550 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800551 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700552 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
553
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800554 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700555 if (hasInputBuf) {
556 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
557 mInflightBuffers.erase(key);
558 }
559 for (size_t i = 0; i < numOutputBufs; i++) {
560 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
561 mInflightBuffers.erase(key);
562 }
563 return Status::INTERNAL_ERROR;
564 }
565
566 return Status::OK;
567}
568
569Return<Status> CameraDeviceSession::flush() {
570 Status status = initStatus();
571 if (status == Status::OK) {
572 // Flush is always supported on device 3.1 or later
573 status_t ret = mDevice->ops->flush(mDevice);
574 if (ret != OK) {
575 status = Status::INTERNAL_ERROR;
576 }
577 }
578 return status;
579}
580
581Return<void> CameraDeviceSession::close() {
582 Mutex::Autolock _l(mStateLock);
583 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800584 {
585 Mutex::Autolock _l(mInflightLock);
586 if (!mInflightBuffers.empty()) {
587 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
588 __FUNCTION__, mInflightBuffers.size());
589 }
590 }
591
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700592 ATRACE_BEGIN("camera3->close");
593 mDevice->common.close(&mDevice->common);
594 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800595
596 // free all imported buffers
597 for(auto& pair : mCirculatingBuffers) {
598 CirculatingBuffers& buffers = pair.second;
599 for (auto& p2 : buffers) {
600 sHandleImporter.freeBuffer(p2.second);
601 }
602 }
603
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700604 mClosed = true;
605 }
606 return Void();
607}
608
609/**
610 * Static callback forwarding methods from HAL to instance
611 */
612void CameraDeviceSession::sProcessCaptureResult(
613 const camera3_callback_ops *cb,
614 const camera3_capture_result *hal_result) {
615 CameraDeviceSession *d =
616 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
617
618 uint32_t frameNumber = hal_result->frame_number;
619 bool hasInputBuf = (hal_result->input_buffer != nullptr);
620 size_t numOutputBufs = hal_result->num_output_buffers;
621 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
622 Status status = Status::OK;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800623 {
624 Mutex::Autolock _l(d->mInflightLock);
625 if (hasInputBuf) {
626 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
627 // validate if buffer is inflight
628 auto key = std::make_pair(streamId, frameNumber);
629 if (d->mInflightBuffers.count(key) != 1) {
630 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
631 __FUNCTION__, streamId, frameNumber);
632 return;
633 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700634 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700635
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800636 for (size_t i = 0; i < numOutputBufs; i++) {
637 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
638 // validate if buffer is inflight
639 auto key = std::make_pair(streamId, frameNumber);
640 if (d->mInflightBuffers.count(key) != 1) {
641 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
642 __FUNCTION__, streamId, frameNumber);
643 return;
644 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700645 }
646 }
647 // We don't need to validate/import fences here since we will be passing them to camera service
648 // within the scope of this function
649
650 CaptureResult result;
651 hidl_vec<native_handle_t*> releaseFences;
652 releaseFences.resize(numBufs);
653 result.frameNumber = frameNumber;
654 result.partialResult = hal_result->partial_result;
655 convertToHidl(hal_result->result, &result.result);
656 if (hasInputBuf) {
657 result.inputBuffer.streamId =
658 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
659 result.inputBuffer.buffer = nullptr;
660 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
661 // skip acquire fence since it's no use to camera service
662 if (hal_result->input_buffer->release_fence != -1) {
663 releaseFences[numOutputBufs] = native_handle_create(/*numFds*/1, /*numInts*/0);
664 releaseFences[numOutputBufs]->data[0] = hal_result->input_buffer->release_fence;
665 result.inputBuffer.releaseFence = releaseFences[numOutputBufs];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800666 } else {
667 releaseFences[numOutputBufs] = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700668 }
669 } else {
670 result.inputBuffer.streamId = -1;
671 }
672
673 result.outputBuffers.resize(numOutputBufs);
674 for (size_t i = 0; i < numOutputBufs; i++) {
675 result.outputBuffers[i].streamId =
676 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
677 result.outputBuffers[i].buffer = nullptr;
678 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
679 // skip acquire fence since it's of no use to camera service
680 if (hal_result->output_buffers[i].release_fence != -1) {
681 releaseFences[i] = native_handle_create(/*numFds*/1, /*numInts*/0);
682 releaseFences[i]->data[0] = hal_result->output_buffers[i].release_fence;
683 result.outputBuffers[i].releaseFence = releaseFences[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800684 } else {
685 releaseFences[i] = nullptr;
686 }
687 }
688
689 // Free inflight record/fences.
690 // Do this before call back to camera service because camera service might jump to
691 // configure_streams right after the processCaptureResult call so we need to finish
692 // updating inflight queues first
693 {
694 Mutex::Autolock _l(d->mInflightLock);
695 if (hasInputBuf) {
696 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
697 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh75846242017-01-09 14:29:06 -0800698 // TODO (b/34169301): currently HAL closed the fence
699 //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800700 d->mInflightBuffers.erase(key);
701 }
702
703 for (size_t i = 0; i < numOutputBufs; i++) {
704 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
705 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh75846242017-01-09 14:29:06 -0800706 // TODO (b/34169301): currently HAL closed the fence
707 //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800708 d->mInflightBuffers.erase(key);
709 }
710
711 if (d->mInflightBuffers.empty()) {
712 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700713 }
714 }
715
716 d->mCallback->processCaptureResult(result);
717
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700718 for (size_t i = 0; i < releaseFences.size(); i++) {
719 // We don't close the FD here as HAL needs to signal it later.
720 native_handle_delete(releaseFences[i]);
721 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700722}
723
724void CameraDeviceSession::sNotify(
725 const camera3_callback_ops *cb,
726 const camera3_notify_msg *msg) {
727 CameraDeviceSession *d =
728 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
729 NotifyMsg hidlMsg;
730 convertToHidl(msg, &hidlMsg);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800731 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
732 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700733 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
734 ALOGE("%s: unknown stream ID %d reports an error!",
735 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
736 }
737 return;
738 }
739 d->mCallback->notify(hidlMsg);
740}
741
742} // namespace implementation
743} // namespace V3_2
744} // namespace device
745} // namespace camera
746} // namespace hardware
747} // namespace android