blob: f37c45bc2e850332e61b02c8c1ddc0b78ec96483 [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);
197 native_handle_close(handle);
198 native_handle_delete(const_cast<native_handle_t*>(handle));
199 }
200 }
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
Emilian Peev98014ff2017-02-02 16:20:12 +0000402 if (status != Status::OK) {
403 _hidl_cb(status, outStreams);
404 return Void();
405 }
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800406
Emilian Peev98014ff2017-02-02 16:20:12 +0000407 camera3_stream_configuration_t stream_list;
408 hidl_vec<camera3_stream_t*> streams;
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800409
Emilian Peev98014ff2017-02-02 16:20:12 +0000410 stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
411 stream_list.num_streams = requestedConfiguration.streams.size();
412 streams.resize(stream_list.num_streams);
413 stream_list.streams = streams.data();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700414
Emilian Peev98014ff2017-02-02 16:20:12 +0000415 for (uint32_t i = 0; i < stream_list.num_streams; i++) {
416 int id = requestedConfiguration.streams[i].id;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700417
Emilian Peev98014ff2017-02-02 16:20:12 +0000418 if (mStreamMap.count(id) == 0) {
419 Camera3Stream stream;
420 convertFromHidl(requestedConfiguration.streams[i], &stream);
421 mStreamMap[id] = stream;
422 mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
423 } else {
424 // width/height/format must not change, but usage/rotation might need to change
425 if (mStreamMap[id].stream_type !=
426 (int) requestedConfiguration.streams[i].streamType ||
427 mStreamMap[id].width != requestedConfiguration.streams[i].width ||
428 mStreamMap[id].height != requestedConfiguration.streams[i].height ||
429 mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
430 mStreamMap[id].data_space != (android_dataspace_t)
431 requestedConfiguration.streams[i].dataSpace) {
432 ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
433 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
434 return Void();
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800435 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000436 mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
437 mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700438 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000439 streams[i] = &mStreamMap[id];
440 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700441
Emilian Peev98014ff2017-02-02 16:20:12 +0000442 ATRACE_BEGIN("camera3->configure_streams");
443 status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
444 ATRACE_END();
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700445
Emilian Peev98014ff2017-02-02 16:20:12 +0000446 // In case Hal returns error most likely it was not able to release
447 // the corresponding resources of the deleted streams.
448 if (ret == OK) {
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800449 // delete unused streams, note we do this after adding new streams to ensure new stream
450 // will not have the same address as deleted stream, and HAL has a chance to reference
451 // the to be deleted stream in configure_streams call
452 for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
453 int id = it->first;
454 bool found = false;
455 for (const auto& stream : requestedConfiguration.streams) {
456 if (id == stream.id) {
457 found = true;
458 break;
459 }
460 }
461 if (!found) {
462 // Unmap all buffers of deleted stream
Emilian Peev98014ff2017-02-02 16:20:12 +0000463 // in case the configuration call succeeds and HAL
464 // is able to release the corresponding resources too.
465 cleanupBuffersLocked(id);
Yin-Chia Yeh9c6dbd52016-12-22 14:55:02 -0800466 it = mStreamMap.erase(it);
467 } else {
468 ++it;
469 }
470 }
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700471 }
Emilian Peev98014ff2017-02-02 16:20:12 +0000472
473 if (ret == -EINVAL) {
474 status = Status::ILLEGAL_ARGUMENT;
475 } else if (ret != OK) {
476 status = Status::INTERNAL_ERROR;
477 } else {
478 convertToHidl(stream_list, &outStreams);
479 }
480
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700481 _hidl_cb(status, outStreams);
482 return Void();
483}
484
Emilian Peev98014ff2017-02-02 16:20:12 +0000485// Needs to get called after acquiring 'mInflightLock'
486void CameraDeviceSession::cleanupBuffersLocked(int id) {
487 for (auto& pair : mCirculatingBuffers.at(id)) {
488 sHandleImporter.freeBuffer(pair.second);
489 }
490 mCirculatingBuffers[id].clear();
491 mCirculatingBuffers.erase(id);
492}
493
Yin-Chia Yehfaef8f92016-10-31 12:53:56 -0700494Return<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 Yehd926f932017-01-09 15:21:11 -0800512 request.inputBuffer.bufferId != 0);
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