blob: de61d831649149d777a0250c6a606b9fd9a26a3f [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) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -080097//TODO(b/34110242): make this hidl transport agnostic
98#ifdef BINDERIZED
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -070099 fd = dup(handle->data[0]);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800100#else
101 fd = handle->data[0];
102#endif
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700103 if (fd < 0) {
104 ALOGE("failed to dup fence fd %d", handle->data[0]);
105 return false;
106 }
107 } else {
108 ALOGE("invalid fence handle with %d file descriptors",
109 handle->numFds);
110 return false;
111 }
112
113 return true;
114 }
115
116 void closeFence(int fd)
117 {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800118#ifdef BINDERIZED
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700119 if (fd >= 0) {
120 close(fd);
121 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800122#else
123 (void) fd;
124#endif
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700125 }
126
127private:
128 bool mInitialized;
129
130 // Some existing gralloc drivers do not support retaining more than once,
131 // when we are in passthrough mode.
132#ifdef BINDERIZED
133 bool openGralloc()
134 {
135 const hw_module_t* module;
136 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
137 if (err) {
138 ALOGE("failed to get gralloc module");
139 return false;
140 }
141
142 uint8_t major = (module->module_api_version >> 8) & 0xff;
143 if (major > 1) {
144 ALOGE("unknown gralloc module major version %d", major);
145 return false;
146 }
147
148 if (major == 1) {
149 err = gralloc1_open(module, &mDevice);
150 if (err) {
151 ALOGE("failed to open gralloc1 device");
152 return false;
153 }
154
155 mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
156 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
157 mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
158 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
159 if (!mRetain || !mRelease) {
160 ALOGE("invalid gralloc1 device");
161 gralloc1_close(mDevice);
162 return false;
163 }
164 } else {
165 mModule = reinterpret_cast<const gralloc_module_t*>(module);
166 }
167
168 return true;
169 }
170
171 void closeGralloc()
172 {
173 if (mDevice) {
174 gralloc1_close(mDevice);
175 }
176 }
177
178 buffer_handle_t cloneBuffer(buffer_handle_t handle)
179 {
180 native_handle_t* clone = native_handle_clone(handle);
181 if (!clone) {
182 ALOGE("failed to clone buffer %p", handle);
183 return nullptr;
184 }
185
186 bool err;
187 if (mDevice) {
188 err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
189 } else {
190 err = (mModule->registerBuffer(mModule, clone) != 0);
191 }
192
193 if (err) {
194 ALOGE("failed to retain/register buffer %p", clone);
195 native_handle_close(clone);
196 native_handle_delete(clone);
197 return nullptr;
198 }
199
200 return clone;
201 }
202
203 void releaseBuffer(buffer_handle_t handle)
204 {
205 if (mDevice) {
206 mRelease(mDevice, handle);
207 } else {
208 mModule->unregisterBuffer(mModule, handle);
209 native_handle_close(handle);
210 native_handle_delete(const_cast<native_handle_t*>(handle));
211 }
212 }
213
214 // gralloc1
215 gralloc1_device_t* mDevice;
216 GRALLOC1_PFN_RETAIN mRetain;
217 GRALLOC1_PFN_RELEASE mRelease;
218
219 // gralloc0
220 const gralloc_module_t* mModule;
221#else
222 bool openGralloc() { return true; }
223 void closeGralloc() {}
224 buffer_handle_t cloneBuffer(buffer_handle_t handle) { return handle; }
225 void releaseBuffer(buffer_handle_t) {}
226#endif
227};
228
229HandleImporter sHandleImporter;
230
231} // Anonymous namespace
232
233CameraDeviceSession::CameraDeviceSession(
234 camera3_device_t* device, const sp<ICameraDeviceCallback>& callback) :
235 camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
236 mDevice(device),
237 mCallback(callback) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700238 // For now, we init sHandleImporter but do not cleanup (keep it alive until
239 // HAL process ends)
240 sHandleImporter.initialize();
241
242 mInitFail = initialize();
243}
244
245bool CameraDeviceSession::initialize() {
246 /** Initialize device with callback functions */
247 ATRACE_BEGIN("camera3->initialize");
248 status_t res = mDevice->ops->initialize(mDevice, this);
249 ATRACE_END();
250
251 if (res != OK) {
252 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
253 __FUNCTION__, strerror(-res), res);
254 mDevice->common.close(&mDevice->common);
255 mClosed = true;
256 return true;
257 }
258 return false;
259}
260
261CameraDeviceSession::~CameraDeviceSession() {
262 if (!isClosed()) {
263 ALOGE("CameraDeviceSession deleted before close!");
264 close();
265 }
266}
267
268bool CameraDeviceSession::isClosed() {
269 Mutex::Autolock _l(mStateLock);
270 return mClosed;
271}
272
273Status CameraDeviceSession::initStatus() const {
274 Mutex::Autolock _l(mStateLock);
275 Status status = Status::OK;
276 if (mInitFail) {
277 status = Status::INTERNAL_ERROR;
278 } else if (mDisconnected) {
279 status = Status::CAMERA_DISCONNECTED;
280 } else if (mClosed) {
281 status = Status::INTERNAL_ERROR;
282 }
283 return status;
284}
285
286void CameraDeviceSession::disconnect() {
287 Mutex::Autolock _l(mStateLock);
288 mDisconnected = true;
289 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
290 if (!mClosed) {
291 mDevice->common.close(&mDevice->common);
292 mClosed = true;
293 }
294}
295
296void CameraDeviceSession::dumpState(const native_handle_t* fd) {
297 if (!isClosed()) {
298 mDevice->ops->dump(mDevice, fd->data[0]);
299 }
300}
301
302Status CameraDeviceSession::importRequest(
303 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800304 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700305 hidl_vec<int>& allFences) {
306 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800307 request.inputBuffer.buffer.getNativeHandle() != nullptr);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700308 size_t numOutputBufs = request.outputBuffers.size();
309 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
310 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800311 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700312 allBufs.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800313 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700314 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800315 std::vector<int32_t> streamIds(numBufs);
316
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700317 for (size_t i = 0; i < numOutputBufs; i++) {
318 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800319 allBufPtrs[i] = &allBufs[i];
320 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700321 }
322 if (hasInputBuf) {
323 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800324 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
325 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700326 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800327
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700328 for (size_t i = 0; i < numBufs; i++) {
329 buffer_handle_t buf = allBufs[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800330 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
331 if (cbs.count(buf) == 0) {
332 // 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 {
339 cbs[buf] = importedBuf;
340 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700341 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800342 allBufPtrs[i] = &cbs[buf];
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 Yeh9c6dbd52016-12-22 14:55:02 -0800509 request.inputBuffer.buffer.getNativeHandle() != nullptr);
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);
698 sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
699 d->mInflightBuffers.erase(key);
700 }
701
702 for (size_t i = 0; i < numOutputBufs; i++) {
703 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
704 auto key = std::make_pair(streamId, frameNumber);
705 sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
706 d->mInflightBuffers.erase(key);
707 }
708
709 if (d->mInflightBuffers.empty()) {
710 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700711 }
712 }
713
714 d->mCallback->processCaptureResult(result);
715
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700716 for (size_t i = 0; i < releaseFences.size(); i++) {
717 // We don't close the FD here as HAL needs to signal it later.
718 native_handle_delete(releaseFences[i]);
719 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700720}
721
722void CameraDeviceSession::sNotify(
723 const camera3_callback_ops *cb,
724 const camera3_notify_msg *msg) {
725 CameraDeviceSession *d =
726 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
727 NotifyMsg hidlMsg;
728 convertToHidl(msg, &hidlMsg);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800729 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
730 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700731 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
732 ALOGE("%s: unknown stream ID %d reports an error!",
733 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
734 }
735 return;
736 }
737 d->mCallback->notify(hidlMsg);
738}
739
740} // namespace implementation
741} // namespace V3_2
742} // namespace device
743} // namespace camera
744} // namespace hardware
745} // namespace android