blob: 201a3b41c13876cc017664bf7a8c8488257845e3 [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 Yeh75846242017-01-09 14:29:06 -0800100 // TODO(b/34169301)
101 // Camera service expect FD be closed by HAL process (in passthrough mode)
102 // close(handle->data[0]);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800103#else
104 fd = handle->data[0];
105#endif
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700106 if (fd < 0) {
107 ALOGE("failed to dup fence fd %d", handle->data[0]);
108 return false;
109 }
110 } else {
111 ALOGE("invalid fence handle with %d file descriptors",
112 handle->numFds);
113 return false;
114 }
115
116 return true;
117 }
118
119 void closeFence(int fd)
120 {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800121#ifdef BINDERIZED
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700122 if (fd >= 0) {
123 close(fd);
124 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800125#else
126 (void) fd;
127#endif
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700128 }
129
130private:
131 bool mInitialized;
132
133 // Some existing gralloc drivers do not support retaining more than once,
134 // when we are in passthrough mode.
135#ifdef BINDERIZED
136 bool openGralloc()
137 {
138 const hw_module_t* module;
139 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
140 if (err) {
141 ALOGE("failed to get gralloc module");
142 return false;
143 }
144
145 uint8_t major = (module->module_api_version >> 8) & 0xff;
146 if (major > 1) {
147 ALOGE("unknown gralloc module major version %d", major);
148 return false;
149 }
150
151 if (major == 1) {
152 err = gralloc1_open(module, &mDevice);
153 if (err) {
154 ALOGE("failed to open gralloc1 device");
155 return false;
156 }
157
158 mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
159 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
160 mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
161 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
162 if (!mRetain || !mRelease) {
163 ALOGE("invalid gralloc1 device");
164 gralloc1_close(mDevice);
165 return false;
166 }
167 } else {
168 mModule = reinterpret_cast<const gralloc_module_t*>(module);
169 }
170
171 return true;
172 }
173
174 void closeGralloc()
175 {
176 if (mDevice) {
177 gralloc1_close(mDevice);
178 }
179 }
180
181 buffer_handle_t cloneBuffer(buffer_handle_t handle)
182 {
183 native_handle_t* clone = native_handle_clone(handle);
184 if (!clone) {
185 ALOGE("failed to clone buffer %p", handle);
186 return nullptr;
187 }
188
189 bool err;
190 if (mDevice) {
191 err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
192 } else {
193 err = (mModule->registerBuffer(mModule, clone) != 0);
194 }
195
196 if (err) {
197 ALOGE("failed to retain/register buffer %p", clone);
198 native_handle_close(clone);
199 native_handle_delete(clone);
200 return nullptr;
201 }
202
203 return clone;
204 }
205
206 void releaseBuffer(buffer_handle_t handle)
207 {
208 if (mDevice) {
209 mRelease(mDevice, handle);
210 } else {
211 mModule->unregisterBuffer(mModule, handle);
212 native_handle_close(handle);
213 native_handle_delete(const_cast<native_handle_t*>(handle));
214 }
215 }
216
217 // gralloc1
218 gralloc1_device_t* mDevice;
219 GRALLOC1_PFN_RETAIN mRetain;
220 GRALLOC1_PFN_RELEASE mRelease;
221
222 // gralloc0
223 const gralloc_module_t* mModule;
224#else
225 bool openGralloc() { return true; }
226 void closeGralloc() {}
227 buffer_handle_t cloneBuffer(buffer_handle_t handle) { return handle; }
228 void releaseBuffer(buffer_handle_t) {}
229#endif
230};
231
232HandleImporter sHandleImporter;
233
234} // Anonymous namespace
235
236CameraDeviceSession::CameraDeviceSession(
237 camera3_device_t* device, const sp<ICameraDeviceCallback>& callback) :
238 camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
239 mDevice(device),
240 mCallback(callback) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700241 // For now, we init sHandleImporter but do not cleanup (keep it alive until
242 // HAL process ends)
243 sHandleImporter.initialize();
244
245 mInitFail = initialize();
246}
247
248bool CameraDeviceSession::initialize() {
249 /** Initialize device with callback functions */
250 ATRACE_BEGIN("camera3->initialize");
251 status_t res = mDevice->ops->initialize(mDevice, this);
252 ATRACE_END();
253
254 if (res != OK) {
255 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
256 __FUNCTION__, strerror(-res), res);
257 mDevice->common.close(&mDevice->common);
258 mClosed = true;
259 return true;
260 }
261 return false;
262}
263
264CameraDeviceSession::~CameraDeviceSession() {
265 if (!isClosed()) {
266 ALOGE("CameraDeviceSession deleted before close!");
267 close();
268 }
269}
270
271bool CameraDeviceSession::isClosed() {
272 Mutex::Autolock _l(mStateLock);
273 return mClosed;
274}
275
276Status CameraDeviceSession::initStatus() const {
277 Mutex::Autolock _l(mStateLock);
278 Status status = Status::OK;
279 if (mInitFail) {
280 status = Status::INTERNAL_ERROR;
281 } else if (mDisconnected) {
282 status = Status::CAMERA_DISCONNECTED;
283 } else if (mClosed) {
284 status = Status::INTERNAL_ERROR;
285 }
286 return status;
287}
288
289void CameraDeviceSession::disconnect() {
290 Mutex::Autolock _l(mStateLock);
291 mDisconnected = true;
292 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
293 if (!mClosed) {
294 mDevice->common.close(&mDevice->common);
295 mClosed = true;
296 }
297}
298
299void CameraDeviceSession::dumpState(const native_handle_t* fd) {
300 if (!isClosed()) {
301 mDevice->ops->dump(mDevice, fd->data[0]);
302 }
303}
304
305Status CameraDeviceSession::importRequest(
306 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800307 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700308 hidl_vec<int>& allFences) {
309 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800310 request.inputBuffer.buffer.getNativeHandle() != nullptr);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700311 size_t numOutputBufs = request.outputBuffers.size();
312 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
313 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800314 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700315 allBufs.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800316 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700317 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800318 std::vector<int32_t> streamIds(numBufs);
319
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700320 for (size_t i = 0; i < numOutputBufs; i++) {
321 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800322 allBufPtrs[i] = &allBufs[i];
323 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700324 }
325 if (hasInputBuf) {
326 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800327 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
328 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700329 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800330
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700331 for (size_t i = 0; i < numBufs; i++) {
332 buffer_handle_t buf = allBufs[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800333 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
334 if (cbs.count(buf) == 0) {
335 // Register a newly seen buffer
336 buffer_handle_t importedBuf = buf;
337 sHandleImporter.importBuffer(importedBuf);
338 if (importedBuf == nullptr) {
339 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
340 return Status::INTERNAL_ERROR;
341 } else {
342 cbs[buf] = importedBuf;
343 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700344 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800345 allBufPtrs[i] = &cbs[buf];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700346 }
347
348 // All buffers are imported. Now validate output buffer acquire fences
349 for (size_t i = 0; i < numOutputBufs; i++) {
350 if (!sHandleImporter.importFence(
351 request.outputBuffers[i].acquireFence, allFences[i])) {
352 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800353 cleanupInflightFences(allFences, i);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700354 return Status::INTERNAL_ERROR;
355 }
356 }
357
358 // Validate input buffer acquire fences
359 if (hasInputBuf) {
360 if (!sHandleImporter.importFence(
361 request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
362 ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800363 cleanupInflightFences(allFences, numOutputBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700364 return Status::INTERNAL_ERROR;
365 }
366 }
367 return Status::OK;
368}
369
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800370void CameraDeviceSession::cleanupInflightFences(
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700371 hidl_vec<int>& allFences, size_t numFences) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700372 for (size_t j = 0; j < numFences; j++) {
373 sHandleImporter.closeFence(allFences[j]);
374 }
375}
376
377// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
378Return<void> CameraDeviceSession::constructDefaultRequestSettings(
379 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
380 Status status = initStatus();
381 CameraMetadata outMetadata;
382 const camera_metadata_t *rawRequest;
383 if (status == Status::OK) {
384 ATRACE_BEGIN("camera3->construct_default_request_settings");
385 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
386 ATRACE_END();
387 if (rawRequest == nullptr) {
388 ALOGI("%s: template %d is not supported on this camera device",
389 __FUNCTION__, type);
390 status = Status::ILLEGAL_ARGUMENT;
391 } else {
392 convertToHidl(rawRequest, &outMetadata);
393 }
394 }
395 _hidl_cb(status, outMetadata);
396 return Void();
397}
398
399Return<void> CameraDeviceSession::configureStreams(
400 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
401 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800402 HalStreamConfiguration outStreams;
403
404 // hold the inflight lock for entire configureStreams scope since there must not be any
405 // inflight request/results during stream configuration.
406 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700407 if (!mInflightBuffers.empty()) {
408 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
409 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800410 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
411 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700412 }
413
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800414
415
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700416 if (status == Status::OK) {
417 camera3_stream_configuration_t stream_list;
418 hidl_vec<camera3_stream_t*> streams;
419
420 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
421 stream_list.num_streams = requestedConfiguration.streams.size();
422 streams.resize(stream_list.num_streams);
423 stream_list.streams = streams.data();
424
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700425 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800426 int id = requestedConfiguration.streams[i].id;
427
428 if (mStreamMap.count(id) == 0) {
429 Camera3Stream stream;
430 convertFromHidl(requestedConfiguration.streams[i], &stream);
431 mStreamMap[id] = stream;
432 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
433 } else {
434 // width/height/format must not change, but usage/rotation might need to change
435 if (mStreamMap[id].stream_type !=
436 (int) requestedConfiguration.streams[i].streamType ||
437 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
438 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
439 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
440 mStreamMap[id].data_space != (android_dataspace_t)
441 requestedConfiguration.streams[i].dataSpace) {
442 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
443 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
444 return Void();
445 }
446 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
447 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
448 }
449 streams[i] = &mStreamMap[id];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700450 }
451
452 ATRACE_BEGIN("camera3->configure_streams");
453 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
454 ATRACE_END();
455
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800456 // delete unused streams, note we do this after adding new streams to ensure new stream
457 // will not have the same address as deleted stream, and HAL has a chance to reference
458 // the to be deleted stream in configure_streams call
459 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
460 int id = it->first;
461 bool found = false;
462 for (const auto& stream : requestedConfiguration.streams) {
463 if (id == stream.id) {
464 found = true;
465 break;
466 }
467 }
468 if (!found) {
469 // Unmap all buffers of deleted stream
470 for (auto& pair : mCirculatingBuffers.at(id)) {
471 sHandleImporter.freeBuffer(pair.second);
472 }
473 mCirculatingBuffers[id].clear();
474 mCirculatingBuffers.erase(id);
475 it = mStreamMap.erase(it);
476 } else {
477 ++it;
478 }
479 }
480
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700481 if (ret == -EINVAL) {
482 status = Status::ILLEGAL_ARGUMENT;
483 } else if (ret != OK) {
484 status = Status::INTERNAL_ERROR;
485 } else {
486 convertToHidl(stream_list, &outStreams);
487 }
488
489 }
490 _hidl_cb(status, outStreams);
491 return Void();
492}
493
494Return<Status> CameraDeviceSession::processCaptureRequest(const CaptureRequest& request) {
495 Status status = initStatus();
496 if (status != Status::OK) {
497 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
498 return status;
499 }
500
501 camera3_capture_request_t halRequest;
502 halRequest.frame_number = request.frameNumber;
503 bool converted = convertFromHidl(request.settings, &halRequest.settings);
504 if (!converted) {
505 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
506 return Status::INTERNAL_ERROR;
507 }
508
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800509 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700510 hidl_vec<int> allFences;
511 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800512 request.inputBuffer.buffer.getNativeHandle() != nullptr);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700513 size_t numOutputBufs = request.outputBuffers.size();
514 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800515 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700516 if (status != Status::OK) {
517 return status;
518 }
519
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700520 hidl_vec<camera3_stream_buffer_t> outHalBufs;
521 outHalBufs.resize(numOutputBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800522 {
523 Mutex::Autolock _l(mInflightLock);
524 if (hasInputBuf) {
525 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
526 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
527 convertFromHidl(
528 allBufPtrs[numOutputBufs], request.inputBuffer.status,
529 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
530 &bufCache);
531 halRequest.input_buffer = &bufCache;
532 } else {
533 halRequest.input_buffer = nullptr;
534 }
535
536 halRequest.num_output_buffers = numOutputBufs;
537 for (size_t i = 0; i < numOutputBufs; i++) {
538 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
539 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
540 convertFromHidl(
541 allBufPtrs[i], request.outputBuffers[i].status,
542 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
543 &bufCache);
544 outHalBufs[i] = bufCache;
545 }
546 halRequest.output_buffers = outHalBufs.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700547 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700548
549 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
550 ATRACE_BEGIN("camera3->process_capture_request");
551 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
552 ATRACE_END();
553 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800554 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700555 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
556
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800557 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700558 if (hasInputBuf) {
559 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
560 mInflightBuffers.erase(key);
561 }
562 for (size_t i = 0; i < numOutputBufs; i++) {
563 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
564 mInflightBuffers.erase(key);
565 }
566 return Status::INTERNAL_ERROR;
567 }
568
569 return Status::OK;
570}
571
572Return<Status> CameraDeviceSession::flush() {
573 Status status = initStatus();
574 if (status == Status::OK) {
575 // Flush is always supported on device 3.1 or later
576 status_t ret = mDevice->ops->flush(mDevice);
577 if (ret != OK) {
578 status = Status::INTERNAL_ERROR;
579 }
580 }
581 return status;
582}
583
584Return<void> CameraDeviceSession::close() {
585 Mutex::Autolock _l(mStateLock);
586 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800587 {
588 Mutex::Autolock _l(mInflightLock);
589 if (!mInflightBuffers.empty()) {
590 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
591 __FUNCTION__, mInflightBuffers.size());
592 }
593 }
594
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700595 ATRACE_BEGIN("camera3->close");
596 mDevice->common.close(&mDevice->common);
597 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800598
599 // free all imported buffers
600 for(auto& pair : mCirculatingBuffers) {
601 CirculatingBuffers& buffers = pair.second;
602 for (auto& p2 : buffers) {
603 sHandleImporter.freeBuffer(p2.second);
604 }
605 }
606
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700607 mClosed = true;
608 }
609 return Void();
610}
611
612/**
613 * Static callback forwarding methods from HAL to instance
614 */
615void CameraDeviceSession::sProcessCaptureResult(
616 const camera3_callback_ops *cb,
617 const camera3_capture_result *hal_result) {
618 CameraDeviceSession *d =
619 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
620
621 uint32_t frameNumber = hal_result->frame_number;
622 bool hasInputBuf = (hal_result->input_buffer != nullptr);
623 size_t numOutputBufs = hal_result->num_output_buffers;
624 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
625 Status status = Status::OK;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800626 {
627 Mutex::Autolock _l(d->mInflightLock);
628 if (hasInputBuf) {
629 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
630 // validate if buffer is inflight
631 auto key = std::make_pair(streamId, frameNumber);
632 if (d->mInflightBuffers.count(key) != 1) {
633 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
634 __FUNCTION__, streamId, frameNumber);
635 return;
636 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700637 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700638
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800639 for (size_t i = 0; i < numOutputBufs; i++) {
640 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
641 // validate if buffer is inflight
642 auto key = std::make_pair(streamId, frameNumber);
643 if (d->mInflightBuffers.count(key) != 1) {
644 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
645 __FUNCTION__, streamId, frameNumber);
646 return;
647 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700648 }
649 }
650 // We don't need to validate/import fences here since we will be passing them to camera service
651 // within the scope of this function
652
653 CaptureResult result;
654 hidl_vec<native_handle_t*> releaseFences;
655 releaseFences.resize(numBufs);
656 result.frameNumber = frameNumber;
657 result.partialResult = hal_result->partial_result;
658 convertToHidl(hal_result->result, &result.result);
659 if (hasInputBuf) {
660 result.inputBuffer.streamId =
661 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
662 result.inputBuffer.buffer = nullptr;
663 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
664 // skip acquire fence since it's no use to camera service
665 if (hal_result->input_buffer->release_fence != -1) {
666 releaseFences[numOutputBufs] = native_handle_create(/*numFds*/1, /*numInts*/0);
667 releaseFences[numOutputBufs]->data[0] = hal_result->input_buffer->release_fence;
668 result.inputBuffer.releaseFence = releaseFences[numOutputBufs];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800669 } else {
670 releaseFences[numOutputBufs] = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700671 }
672 } else {
673 result.inputBuffer.streamId = -1;
674 }
675
676 result.outputBuffers.resize(numOutputBufs);
677 for (size_t i = 0; i < numOutputBufs; i++) {
678 result.outputBuffers[i].streamId =
679 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
680 result.outputBuffers[i].buffer = nullptr;
681 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
682 // skip acquire fence since it's of no use to camera service
683 if (hal_result->output_buffers[i].release_fence != -1) {
684 releaseFences[i] = native_handle_create(/*numFds*/1, /*numInts*/0);
685 releaseFences[i]->data[0] = hal_result->output_buffers[i].release_fence;
686 result.outputBuffers[i].releaseFence = releaseFences[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800687 } else {
688 releaseFences[i] = nullptr;
689 }
690 }
691
692 // Free inflight record/fences.
693 // Do this before call back to camera service because camera service might jump to
694 // configure_streams right after the processCaptureResult call so we need to finish
695 // updating inflight queues first
696 {
697 Mutex::Autolock _l(d->mInflightLock);
698 if (hasInputBuf) {
699 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
700 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh75846242017-01-09 14:29:06 -0800701 // TODO (b/34169301): currently HAL closed the fence
702 //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800703 d->mInflightBuffers.erase(key);
704 }
705
706 for (size_t i = 0; i < numOutputBufs; i++) {
707 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
708 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh75846242017-01-09 14:29:06 -0800709 // TODO (b/34169301): currently HAL closed the fence
710 //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800711 d->mInflightBuffers.erase(key);
712 }
713
714 if (d->mInflightBuffers.empty()) {
715 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700716 }
717 }
718
719 d->mCallback->processCaptureResult(result);
720
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700721 for (size_t i = 0; i < releaseFences.size(); i++) {
722 // We don't close the FD here as HAL needs to signal it later.
723 native_handle_delete(releaseFences[i]);
724 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700725}
726
727void CameraDeviceSession::sNotify(
728 const camera3_callback_ops *cb,
729 const camera3_notify_msg *msg) {
730 CameraDeviceSession *d =
731 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
732 NotifyMsg hidlMsg;
733 convertToHidl(msg, &hidlMsg);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800734 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
735 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700736 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
737 ALOGE("%s: unknown stream ID %d reports an error!",
738 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
739 }
740 return;
741 }
742 d->mCallback->notify(hidlMsg);
743}
744
745} // namespace implementation
746} // namespace V3_2
747} // namespace device
748} // namespace camera
749} // namespace hardware
750} // namespace android