blob: 76310ef6331767be226697f41d6001c8eb2db452 [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
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700121 bool openGralloc()
122 {
123 const hw_module_t* module;
124 int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
125 if (err) {
126 ALOGE("failed to get gralloc module");
127 return false;
128 }
129
130 uint8_t major = (module->module_api_version >> 8) & 0xff;
131 if (major > 1) {
132 ALOGE("unknown gralloc module major version %d", major);
133 return false;
134 }
135
136 if (major == 1) {
137 err = gralloc1_open(module, &mDevice);
138 if (err) {
139 ALOGE("failed to open gralloc1 device");
140 return false;
141 }
142
143 mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
144 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
145 mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
146 mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
147 if (!mRetain || !mRelease) {
148 ALOGE("invalid gralloc1 device");
149 gralloc1_close(mDevice);
150 return false;
151 }
152 } else {
153 mModule = reinterpret_cast<const gralloc_module_t*>(module);
154 }
155
156 return true;
157 }
158
159 void closeGralloc()
160 {
161 if (mDevice) {
162 gralloc1_close(mDevice);
163 }
164 }
165
166 buffer_handle_t cloneBuffer(buffer_handle_t handle)
167 {
168 native_handle_t* clone = native_handle_clone(handle);
169 if (!clone) {
170 ALOGE("failed to clone buffer %p", handle);
171 return nullptr;
172 }
173
174 bool err;
175 if (mDevice) {
176 err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
177 } else {
178 err = (mModule->registerBuffer(mModule, clone) != 0);
179 }
180
181 if (err) {
182 ALOGE("failed to retain/register buffer %p", clone);
183 native_handle_close(clone);
184 native_handle_delete(clone);
185 return nullptr;
186 }
187
188 return clone;
189 }
190
191 void releaseBuffer(buffer_handle_t handle)
192 {
193 if (mDevice) {
194 mRelease(mDevice, handle);
195 } else {
196 mModule->unregisterBuffer(mModule, handle);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700197 }
Emilian Peevbbdb1f62017-02-13 15:26:00 +0000198 native_handle_close(handle);
199 native_handle_delete(const_cast<native_handle_t*>(handle));
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700200 }
201
202 // gralloc1
203 gralloc1_device_t* mDevice;
204 GRALLOC1_PFN_RETAIN mRetain;
205 GRALLOC1_PFN_RELEASE mRelease;
206
207 // gralloc0
208 const gralloc_module_t* mModule;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700209};
210
211HandleImporter sHandleImporter;
212
213} // Anonymous namespace
214
215CameraDeviceSession::CameraDeviceSession(
216 camera3_device_t* device, const sp<ICameraDeviceCallback>& callback) :
217 camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
218 mDevice(device),
219 mCallback(callback) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700220 // For now, we init sHandleImporter but do not cleanup (keep it alive until
221 // HAL process ends)
222 sHandleImporter.initialize();
223
224 mInitFail = initialize();
225}
226
227bool CameraDeviceSession::initialize() {
228 /** Initialize device with callback functions */
229 ATRACE_BEGIN("camera3->initialize");
230 status_t res = mDevice->ops->initialize(mDevice, this);
231 ATRACE_END();
232
233 if (res != OK) {
234 ALOGE("%s: Unable to initialize HAL device: %s (%d)",
235 __FUNCTION__, strerror(-res), res);
236 mDevice->common.close(&mDevice->common);
237 mClosed = true;
238 return true;
239 }
240 return false;
241}
242
243CameraDeviceSession::~CameraDeviceSession() {
244 if (!isClosed()) {
245 ALOGE("CameraDeviceSession deleted before close!");
246 close();
247 }
248}
249
250bool CameraDeviceSession::isClosed() {
251 Mutex::Autolock _l(mStateLock);
252 return mClosed;
253}
254
255Status CameraDeviceSession::initStatus() const {
256 Mutex::Autolock _l(mStateLock);
257 Status status = Status::OK;
258 if (mInitFail) {
259 status = Status::INTERNAL_ERROR;
260 } else if (mDisconnected) {
261 status = Status::CAMERA_DISCONNECTED;
262 } else if (mClosed) {
263 status = Status::INTERNAL_ERROR;
264 }
265 return status;
266}
267
268void CameraDeviceSession::disconnect() {
269 Mutex::Autolock _l(mStateLock);
270 mDisconnected = true;
271 ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
272 if (!mClosed) {
273 mDevice->common.close(&mDevice->common);
274 mClosed = true;
275 }
276}
277
278void CameraDeviceSession::dumpState(const native_handle_t* fd) {
279 if (!isClosed()) {
280 mDevice->ops->dump(mDevice, fd->data[0]);
281 }
282}
283
284Status CameraDeviceSession::importRequest(
285 const CaptureRequest& request,
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800286 hidl_vec<buffer_handle_t*>& allBufPtrs,
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700287 hidl_vec<int>& allFences) {
288 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800289 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700290 size_t numOutputBufs = request.outputBuffers.size();
291 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
292 // Validate all I/O buffers
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800293 hidl_vec<buffer_handle_t> allBufs;
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800294 hidl_vec<uint64_t> allBufIds;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700295 allBufs.resize(numBufs);
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800296 allBufIds.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800297 allBufPtrs.resize(numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700298 allFences.resize(numBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800299 std::vector<int32_t> streamIds(numBufs);
300
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700301 for (size_t i = 0; i < numOutputBufs; i++) {
302 allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800303 allBufIds[i] = request.outputBuffers[i].bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800304 allBufPtrs[i] = &allBufs[i];
305 streamIds[i] = request.outputBuffers[i].streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700306 }
307 if (hasInputBuf) {
308 allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800309 allBufIds[numOutputBufs] = request.inputBuffer.bufferId;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800310 allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
311 streamIds[numOutputBufs] = request.inputBuffer.streamId;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700312 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800313
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700314 for (size_t i = 0; i < numBufs; i++) {
315 buffer_handle_t buf = allBufs[i];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800316 uint64_t bufId = allBufIds[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800317 CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800318 if (cbs.count(bufId) == 0) {
319 if (buf == nullptr) {
320 ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
321 return Status::ILLEGAL_ARGUMENT;
322 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800323 // Register a newly seen buffer
324 buffer_handle_t importedBuf = buf;
325 sHandleImporter.importBuffer(importedBuf);
326 if (importedBuf == nullptr) {
327 ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
328 return Status::INTERNAL_ERROR;
329 } else {
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800330 cbs[bufId] = importedBuf;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800331 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700332 }
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800333 allBufPtrs[i] = &cbs[bufId];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700334 }
335
336 // All buffers are imported. Now validate output buffer acquire fences
337 for (size_t i = 0; i < numOutputBufs; i++) {
338 if (!sHandleImporter.importFence(
339 request.outputBuffers[i].acquireFence, allFences[i])) {
340 ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800341 cleanupInflightFences(allFences, i);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700342 return Status::INTERNAL_ERROR;
343 }
344 }
345
346 // Validate input buffer acquire fences
347 if (hasInputBuf) {
348 if (!sHandleImporter.importFence(
349 request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
350 ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800351 cleanupInflightFences(allFences, numOutputBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700352 return Status::INTERNAL_ERROR;
353 }
354 }
355 return Status::OK;
356}
357
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800358void CameraDeviceSession::cleanupInflightFences(
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700359 hidl_vec<int>& allFences, size_t numFences) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700360 for (size_t j = 0; j < numFences; j++) {
361 sHandleImporter.closeFence(allFences[j]);
362 }
363}
364
365// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
366Return<void> CameraDeviceSession::constructDefaultRequestSettings(
367 RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) {
368 Status status = initStatus();
369 CameraMetadata outMetadata;
370 const camera_metadata_t *rawRequest;
371 if (status == Status::OK) {
372 ATRACE_BEGIN("camera3->construct_default_request_settings");
373 rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
374 ATRACE_END();
375 if (rawRequest == nullptr) {
376 ALOGI("%s: template %d is not supported on this camera device",
377 __FUNCTION__, type);
378 status = Status::ILLEGAL_ARGUMENT;
379 } else {
380 convertToHidl(rawRequest, &outMetadata);
381 }
382 }
383 _hidl_cb(status, outMetadata);
384 return Void();
385}
386
387Return<void> CameraDeviceSession::configureStreams(
388 const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) {
389 Status status = initStatus();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800390 HalStreamConfiguration outStreams;
391
392 // hold the inflight lock for entire configureStreams scope since there must not be any
393 // inflight request/results during stream configuration.
394 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700395 if (!mInflightBuffers.empty()) {
396 ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
397 __FUNCTION__, mInflightBuffers.size());
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800398 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
399 return Void();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700400 }
401
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800402
403
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700404 if (status == Status::OK) {
405 camera3_stream_configuration_t stream_list;
406 hidl_vec<camera3_stream_t*> streams;
407
408 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
409 stream_list.num_streams = requestedConfiguration.streams.size();
410 streams.resize(stream_list.num_streams);
411 stream_list.streams = streams.data();
412
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700413 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800414 int id = requestedConfiguration.streams[i].id;
415
416 if (mStreamMap.count(id) == 0) {
417 Camera3Stream stream;
418 convertFromHidl(requestedConfiguration.streams[i], &stream);
419 mStreamMap[id] = stream;
420 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
421 } else {
422 // width/height/format must not change, but usage/rotation might need to change
423 if (mStreamMap[id].stream_type !=
424 (int) requestedConfiguration.streams[i].streamType ||
425 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
426 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
427 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
428 mStreamMap[id].data_space != (android_dataspace_t)
429 requestedConfiguration.streams[i].dataSpace) {
430 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
431 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
432 return Void();
433 }
434 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
435 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
436 }
437 streams[i] = &mStreamMap[id];
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700438 }
439
440 ATRACE_BEGIN("camera3->configure_streams");
441 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
442 ATRACE_END();
443
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800444 // delete unused streams, note we do this after adding new streams to ensure new stream
445 // will not have the same address as deleted stream, and HAL has a chance to reference
446 // the to be deleted stream in configure_streams call
447 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
448 int id = it->first;
449 bool found = false;
450 for (const auto& stream : requestedConfiguration.streams) {
451 if (id == stream.id) {
452 found = true;
453 break;
454 }
455 }
456 if (!found) {
457 // Unmap all buffers of deleted stream
458 for (auto& pair : mCirculatingBuffers.at(id)) {
459 sHandleImporter.freeBuffer(pair.second);
460 }
461 mCirculatingBuffers[id].clear();
462 mCirculatingBuffers.erase(id);
463 it = mStreamMap.erase(it);
464 } else {
465 ++it;
466 }
467 }
468
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700469 if (ret == -EINVAL) {
470 status = Status::ILLEGAL_ARGUMENT;
471 } else if (ret != OK) {
472 status = Status::INTERNAL_ERROR;
473 } else {
474 convertToHidl(stream_list, &outStreams);
475 }
476
477 }
478 _hidl_cb(status, outStreams);
479 return Void();
480}
481
482Return<Status> CameraDeviceSession::processCaptureRequest(const CaptureRequest& request) {
483 Status status = initStatus();
484 if (status != Status::OK) {
485 ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
486 return status;
487 }
488
489 camera3_capture_request_t halRequest;
490 halRequest.frame_number = request.frameNumber;
491 bool converted = convertFromHidl(request.settings, &halRequest.settings);
492 if (!converted) {
493 ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
494 return Status::INTERNAL_ERROR;
495 }
496
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800497 hidl_vec<buffer_handle_t*> allBufPtrs;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700498 hidl_vec<int> allFences;
499 bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
Yin-Chia Yehd926f932017-01-09 15:21:11 -0800500 request.inputBuffer.bufferId != 0);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700501 size_t numOutputBufs = request.outputBuffers.size();
502 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800503 status = importRequest(request, allBufPtrs, allFences);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700504 if (status != Status::OK) {
505 return status;
506 }
507
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700508 hidl_vec<camera3_stream_buffer_t> outHalBufs;
509 outHalBufs.resize(numOutputBufs);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800510 {
511 Mutex::Autolock _l(mInflightLock);
512 if (hasInputBuf) {
513 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
514 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
515 convertFromHidl(
516 allBufPtrs[numOutputBufs], request.inputBuffer.status,
517 &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
518 &bufCache);
519 halRequest.input_buffer = &bufCache;
520 } else {
521 halRequest.input_buffer = nullptr;
522 }
523
524 halRequest.num_output_buffers = numOutputBufs;
525 for (size_t i = 0; i < numOutputBufs; i++) {
526 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
527 auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
528 convertFromHidl(
529 allBufPtrs[i], request.outputBuffers[i].status,
530 &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
531 &bufCache);
532 outHalBufs[i] = bufCache;
533 }
534 halRequest.output_buffers = outHalBufs.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700535 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700536
537 ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
538 ATRACE_BEGIN("camera3->process_capture_request");
539 status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
540 ATRACE_END();
541 if (ret != OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800542 Mutex::Autolock _l(mInflightLock);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700543 ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
544
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800545 cleanupInflightFences(allFences, numBufs);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700546 if (hasInputBuf) {
547 auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
548 mInflightBuffers.erase(key);
549 }
550 for (size_t i = 0; i < numOutputBufs; i++) {
551 auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
552 mInflightBuffers.erase(key);
553 }
554 return Status::INTERNAL_ERROR;
555 }
556
557 return Status::OK;
558}
559
560Return<Status> CameraDeviceSession::flush() {
561 Status status = initStatus();
562 if (status == Status::OK) {
563 // Flush is always supported on device 3.1 or later
564 status_t ret = mDevice->ops->flush(mDevice);
565 if (ret != OK) {
566 status = Status::INTERNAL_ERROR;
567 }
568 }
569 return status;
570}
571
572Return<void> CameraDeviceSession::close() {
573 Mutex::Autolock _l(mStateLock);
574 if (!mClosed) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800575 {
576 Mutex::Autolock _l(mInflightLock);
577 if (!mInflightBuffers.empty()) {
578 ALOGE("%s: trying to close while there are still %zu inflight buffers!",
579 __FUNCTION__, mInflightBuffers.size());
580 }
581 }
582
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700583 ATRACE_BEGIN("camera3->close");
584 mDevice->common.close(&mDevice->common);
585 ATRACE_END();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800586
587 // free all imported buffers
588 for(auto& pair : mCirculatingBuffers) {
589 CirculatingBuffers& buffers = pair.second;
590 for (auto& p2 : buffers) {
591 sHandleImporter.freeBuffer(p2.second);
592 }
593 }
594
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700595 mClosed = true;
596 }
597 return Void();
598}
599
600/**
601 * Static callback forwarding methods from HAL to instance
602 */
603void CameraDeviceSession::sProcessCaptureResult(
604 const camera3_callback_ops *cb,
605 const camera3_capture_result *hal_result) {
606 CameraDeviceSession *d =
607 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
608
609 uint32_t frameNumber = hal_result->frame_number;
610 bool hasInputBuf = (hal_result->input_buffer != nullptr);
611 size_t numOutputBufs = hal_result->num_output_buffers;
612 size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
613 Status status = Status::OK;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800614 {
615 Mutex::Autolock _l(d->mInflightLock);
616 if (hasInputBuf) {
617 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
618 // validate if buffer is inflight
619 auto key = std::make_pair(streamId, frameNumber);
620 if (d->mInflightBuffers.count(key) != 1) {
621 ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
622 __FUNCTION__, streamId, frameNumber);
623 return;
624 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700625 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700626
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800627 for (size_t i = 0; i < numOutputBufs; i++) {
628 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
629 // validate if buffer is inflight
630 auto key = std::make_pair(streamId, frameNumber);
631 if (d->mInflightBuffers.count(key) != 1) {
632 ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
633 __FUNCTION__, streamId, frameNumber);
634 return;
635 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700636 }
637 }
638 // We don't need to validate/import fences here since we will be passing them to camera service
639 // within the scope of this function
640
641 CaptureResult result;
642 hidl_vec<native_handle_t*> releaseFences;
643 releaseFences.resize(numBufs);
644 result.frameNumber = frameNumber;
645 result.partialResult = hal_result->partial_result;
646 convertToHidl(hal_result->result, &result.result);
647 if (hasInputBuf) {
648 result.inputBuffer.streamId =
649 static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
650 result.inputBuffer.buffer = nullptr;
651 result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
652 // skip acquire fence since it's no use to camera service
653 if (hal_result->input_buffer->release_fence != -1) {
654 releaseFences[numOutputBufs] = native_handle_create(/*numFds*/1, /*numInts*/0);
655 releaseFences[numOutputBufs]->data[0] = hal_result->input_buffer->release_fence;
656 result.inputBuffer.releaseFence = releaseFences[numOutputBufs];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800657 } else {
658 releaseFences[numOutputBufs] = nullptr;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700659 }
660 } else {
661 result.inputBuffer.streamId = -1;
662 }
663
664 result.outputBuffers.resize(numOutputBufs);
665 for (size_t i = 0; i < numOutputBufs; i++) {
666 result.outputBuffers[i].streamId =
667 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
668 result.outputBuffers[i].buffer = nullptr;
669 result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
670 // skip acquire fence since it's of no use to camera service
671 if (hal_result->output_buffers[i].release_fence != -1) {
672 releaseFences[i] = native_handle_create(/*numFds*/1, /*numInts*/0);
673 releaseFences[i]->data[0] = hal_result->output_buffers[i].release_fence;
674 result.outputBuffers[i].releaseFence = releaseFences[i];
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800675 } else {
676 releaseFences[i] = nullptr;
677 }
678 }
679
680 // Free inflight record/fences.
681 // Do this before call back to camera service because camera service might jump to
682 // configure_streams right after the processCaptureResult call so we need to finish
683 // updating inflight queues first
684 {
685 Mutex::Autolock _l(d->mInflightLock);
686 if (hasInputBuf) {
687 int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
688 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh75846242017-01-09 14:29:06 -0800689 // TODO (b/34169301): currently HAL closed the fence
690 //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800691 d->mInflightBuffers.erase(key);
692 }
693
694 for (size_t i = 0; i < numOutputBufs; i++) {
695 int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
696 auto key = std::make_pair(streamId, frameNumber);
Yin-Chia Yeh75846242017-01-09 14:29:06 -0800697 // TODO (b/34169301): currently HAL closed the fence
698 //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800699 d->mInflightBuffers.erase(key);
700 }
701
702 if (d->mInflightBuffers.empty()) {
703 ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700704 }
705 }
706
707 d->mCallback->processCaptureResult(result);
708
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700709 for (size_t i = 0; i < releaseFences.size(); i++) {
710 // We don't close the FD here as HAL needs to signal it later.
711 native_handle_delete(releaseFences[i]);
712 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700713}
714
715void CameraDeviceSession::sNotify(
716 const camera3_callback_ops *cb,
717 const camera3_notify_msg *msg) {
718 CameraDeviceSession *d =
719 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
720 NotifyMsg hidlMsg;
721 convertToHidl(msg, &hidlMsg);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800722 if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
723 hidlMsg.msg.error.errorStreamId != -1) {
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700724 if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
725 ALOGE("%s: unknown stream ID %d reports an error!",
726 __FUNCTION__, hidlMsg.msg.error.errorStreamId);
727 }
728 return;
729 }
730 d->mCallback->notify(hidlMsg);
731}
732
733} // namespace implementation
734} // namespace V3_2
735} // namespace device
736} // namespace camera
737} // namespace hardware
738} // namespace android