blob: 873ddd04605c440c0d381ba3e5f05bf6eb588856 [file] [log] [blame]
Yin-Chia Yeh6a6fe0f2018-09-06 15:38:34 -07001/*
2 * Copyright (C) 2018 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.5-impl"
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070018#define ATRACE_TAG ATRACE_TAG_CAMERA
Yin-Chia Yeh6a6fe0f2018-09-06 15:38:34 -070019#include <android/log.h>
20
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070021#include <vector>
Yin-Chia Yeh6a6fe0f2018-09-06 15:38:34 -070022#include <utils/Trace.h>
23#include "CameraDeviceSession.h"
24
25namespace android {
26namespace hardware {
27namespace camera {
28namespace device {
29namespace V3_5 {
30namespace implementation {
31
32CameraDeviceSession::CameraDeviceSession(
33 camera3_device_t* device,
34 const camera_metadata_t* deviceInfo,
35 const sp<V3_2::ICameraDeviceCallback>& callback) :
36 V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) {
37
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070038 mCallback_3_5 = nullptr;
Yin-Chia Yeh6a6fe0f2018-09-06 15:38:34 -070039
40 auto castResult = ICameraDeviceCallback::castFrom(callback);
41 if (castResult.isOk()) {
42 sp<ICameraDeviceCallback> callback3_5 = castResult;
43 if (callback3_5 != nullptr) {
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070044 mCallback_3_5 = callback3_5;
45 }
46 }
47
48 if (mCallback_3_5 != nullptr) {
49 camera_metadata_entry bufMgrVersion = mDeviceInfo.find(
50 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
51 if (bufMgrVersion.count > 0) {
52 mSupportBufMgr = (bufMgrVersion.data.u8[0] ==
53 ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
54 if (mSupportBufMgr) {
55 request_stream_buffers = sRequestStreamBuffers;
56 return_stream_buffers = sReturnStreamBuffers;
57 }
Yin-Chia Yeh6a6fe0f2018-09-06 15:38:34 -070058 }
59 }
60}
61
62CameraDeviceSession::~CameraDeviceSession() {
63}
64
65Return<void> CameraDeviceSession::configureStreams_3_5(
Yin-Chia Yeh86a7d962018-10-15 14:20:15 -070066 const StreamConfiguration& requestedConfiguration,
Yin-Chia Yeh6a6fe0f2018-09-06 15:38:34 -070067 ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) {
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070068 configureStreams_3_4_Impl(requestedConfiguration.v3_4, _hidl_cb,
69 requestedConfiguration.streamConfigCounter);
70 return Void();
Yin-Chia Yeh6a6fe0f2018-09-06 15:38:34 -070071}
72
73Return<void> CameraDeviceSession::signalStreamFlush(
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070074 const hidl_vec<int32_t>& streamIds, uint32_t streamConfigCounter) {
75 std::vector<camera3_stream_t*> streams(streamIds.size());
76 {
77 Mutex::Autolock _l(mInflightLock);
78 for (size_t i = 0; i < streamIds.size(); i++) {
79 int32_t id = streamIds[i];
80 if (mStreamMap.count(id) == 0) {
81 ALOGE("%s: unknown streamId %d", __FUNCTION__, id);
82 return Void();
83 }
84 streams[i] = &mStreamMap[id];
85 }
86 }
87 if (mDevice->ops->signal_stream_flush != nullptr) {
88 mDevice->ops->signal_stream_flush(mDevice,
89 streamConfigCounter, streams.size(), streams.data());
90 }
Yin-Chia Yeh6a6fe0f2018-09-06 15:38:34 -070091 return Void();
92}
93
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -070094Status CameraDeviceSession::importRequest(
95 const CaptureRequest& request,
96 hidl_vec<buffer_handle_t*>& allBufPtrs,
97 hidl_vec<int>& allFences) {
98 if (mSupportBufMgr) {
99 return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ true);
100 }
101 return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ false);
102}
103
104void CameraDeviceSession::pushBufferId(
105 const buffer_handle_t& buf, uint64_t bufferId, int streamId) {
106 std::lock_guard<std::mutex> lock(mBufferIdMapLock);
107
108 // emplace will return existing entry if there is one.
109 auto pair = mBufferIdMaps.emplace(streamId, BufferIdMap{});
110 BufferIdMap& bIdMap = pair.first->second;
111 bIdMap[buf] = bufferId;
112}
113
114uint64_t CameraDeviceSession::popBufferId(
115 const buffer_handle_t& buf, int streamId) {
116 std::lock_guard<std::mutex> lock(mBufferIdMapLock);
117
118 auto streamIt = mBufferIdMaps.find(streamId);
119 if (streamIt == mBufferIdMaps.end()) {
120 return BUFFER_ID_NO_BUFFER;
121 }
122 BufferIdMap& bIdMap = streamIt->second;
123 auto it = bIdMap.find(buf);
124 if (it == bIdMap.end()) {
125 return BUFFER_ID_NO_BUFFER;
126 }
127 uint64_t bufId = it->second;
128 bIdMap.erase(it);
129 if (bIdMap.empty()) {
130 mBufferIdMaps.erase(streamIt);
131 }
132 return bufId;
133}
134
135uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t& buf, int streamId) {
136 if (mSupportBufMgr) {
137 return popBufferId(buf, streamId);
138 }
139 return BUFFER_ID_NO_BUFFER;
140}
141
142Camera3Stream* CameraDeviceSession::getStreamPointer(int32_t streamId) {
143 Mutex::Autolock _l(mInflightLock);
144 if (mStreamMap.count(streamId) == 0) {
145 ALOGE("%s: unknown streamId %d", __FUNCTION__, streamId);
146 return nullptr;
147 }
148 return &mStreamMap[streamId];
149}
150
151void CameraDeviceSession::cleanupInflightBufferFences(
152 std::vector<int>& fences, std::vector<std::pair<buffer_handle_t, int>>& bufs) {
153 hidl_vec<int> hFences = fences;
154 cleanupInflightFences(hFences, fences.size());
155 for (auto& p : bufs) {
156 popBufferId(p.first, p.second);
157 }
158}
159
160camera3_buffer_request_status_t CameraDeviceSession::requestStreamBuffers(
161 uint32_t num_buffer_reqs,
162 const camera3_buffer_request_t *buffer_reqs,
163 /*out*/uint32_t *num_returned_buf_reqs,
164 /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
165 ATRACE_CALL();
166 *num_returned_buf_reqs = 0;
167 hidl_vec<BufferRequest> hBufReqs(num_buffer_reqs);
168 for (size_t i = 0; i < num_buffer_reqs; i++) {
169 hBufReqs[i].streamId =
170 static_cast<Camera3Stream*>(buffer_reqs[i].stream)->mId;
171 hBufReqs[i].numBuffersRequested = buffer_reqs[i].num_buffers_requested;
172 }
173
174 ATRACE_BEGIN("HIDL requestStreamBuffers");
175 BufferRequestStatus status;
176 hidl_vec<StreamBufferRet> bufRets;
177 auto err = mCallback_3_5->requestStreamBuffers(hBufReqs,
178 [&status, &bufRets]
179 (BufferRequestStatus s, const hidl_vec<StreamBufferRet>& rets) {
180 status = s;
181 bufRets = std::move(rets);
182 });
183 if (!err.isOk()) {
184 ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
185 return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
186 }
187 ATRACE_END();
188
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700189 switch (status) {
190 case BufferRequestStatus::FAILED_CONFIGURING:
191 return CAMERA3_BUF_REQ_FAILED_CONFIGURING;
192 case BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS:
193 return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700194 default:
Yin-Chia Yeh71e62982019-02-08 14:35:58 -0800195 break; // Other status Handled by following code
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700196 }
Yin-Chia Yeh71e62982019-02-08 14:35:58 -0800197
198 if (status != BufferRequestStatus::OK && status != BufferRequestStatus::FAILED_PARTIAL &&
199 status != BufferRequestStatus::FAILED_UNKNOWN) {
200 ALOGE("%s: unknown buffer request error code %d", __FUNCTION__, status);
201 return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
202 }
203
204 // Only OK, FAILED_PARTIAL and FAILED_UNKNOWN reaches here
205 if (bufRets.size() != num_buffer_reqs) {
206 ALOGE("%s: expect %d buffer requests returned, only got %zu",
207 __FUNCTION__, num_buffer_reqs, bufRets.size());
208 return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
209 }
210
211 *num_returned_buf_reqs = num_buffer_reqs;
212 for (size_t i = 0; i < num_buffer_reqs; i++) {
213 // maybe we can query all streams in one call to avoid frequent locking device here?
214 Camera3Stream* stream = getStreamPointer(bufRets[i].streamId);
215 if (stream == nullptr) {
216 ALOGE("%s: unknown streamId %d", __FUNCTION__, bufRets[i].streamId);
217 return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
218 }
219 returned_buf_reqs[i].stream = stream;
220 }
221
222 // Handle failed streams
223 for (size_t i = 0; i < num_buffer_reqs; i++) {
224 if (bufRets[i].val.getDiscriminator() == StreamBuffersVal::hidl_discriminator::error) {
225 returned_buf_reqs[i].num_output_buffers = 0;
226 switch (bufRets[i].val.error()) {
227 case StreamBufferRequestError::NO_BUFFER_AVAILABLE:
228 returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_NO_BUFFER_AVAILABLE;
229 break;
230 case StreamBufferRequestError::MAX_BUFFER_EXCEEDED:
231 returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_MAX_BUFFER_EXCEEDED;
232 break;
233 case StreamBufferRequestError::STREAM_DISCONNECTED:
234 returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_STREAM_DISCONNECTED;
235 break;
236 case StreamBufferRequestError::UNKNOWN_ERROR:
237 returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR;
238 break;
239 default:
240 ALOGE("%s: Unknown StreamBufferRequestError %d",
241 __FUNCTION__, bufRets[i].val.error());
242 return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
243 }
244 }
245 }
246
247 if (status == BufferRequestStatus::FAILED_UNKNOWN) {
248 return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
249 }
250
251 // Only BufferRequestStatus::OK and BufferRequestStatus::FAILED_PARTIAL reaches here
252 std::vector<int> importedFences;
253 std::vector<std::pair<buffer_handle_t, int>> importedBuffers;
254 for (size_t i = 0; i < num_buffer_reqs; i++) {
255 if (bufRets[i].val.getDiscriminator() !=
256 StreamBuffersVal::hidl_discriminator::buffers) {
257 continue;
258 }
259 int streamId = bufRets[i].streamId;
260 const hidl_vec<StreamBuffer>& hBufs = bufRets[i].val.buffers();
261 camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers;
262 for (size_t b = 0; b < hBufs.size(); b++) {
263 const StreamBuffer& hBuf = hBufs[b];
264 camera3_stream_buffer_t& outBuf = outBufs[b];
265 // maybe add importBuffers API to avoid frequent locking device?
266 Status s = importBuffer(streamId,
267 hBuf.bufferId, hBuf.buffer.getNativeHandle(),
268 /*out*/&(outBuf.buffer),
269 /*allowEmptyBuf*/false);
270 if (s != Status::OK) {
271 ALOGE("%s: import stream %d bufferId %" PRIu64 " failed!",
272 __FUNCTION__, streamId, hBuf.bufferId);
273 cleanupInflightBufferFences(importedFences, importedBuffers);
274 // Buffer import should never fail - restart HAL since something is very
275 // wrong.
276 assert(false);
277 return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
278 }
279
280 pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId);
281 importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId));
282
283 if (!sHandleImporter.importFence(
284 hBuf.acquireFence,
285 outBuf.acquire_fence)) {
286 ALOGE("%s: stream %d bufferId %" PRIu64 "acquire fence is invalid",
287 __FUNCTION__, streamId, hBuf.bufferId);
288 cleanupInflightBufferFences(importedFences, importedBuffers);
289 return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
290 }
291 importedFences.push_back(outBuf.acquire_fence);
292 outBuf.stream = returned_buf_reqs[i].stream;
293 outBuf.status = CAMERA3_BUFFER_STATUS_OK;
294 outBuf.release_fence = -1;
295 }
296 returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_OK;
297 }
298
299 return (status == BufferRequestStatus::OK) ?
300 CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL;
Yin-Chia Yehc2d3d1d2018-09-20 15:06:13 -0700301}
302
303void CameraDeviceSession::returnStreamBuffers(
304 uint32_t num_buffers,
305 const camera3_stream_buffer_t* const* buffers) {
306 ATRACE_CALL();
307 hidl_vec<StreamBuffer> hBufs(num_buffers);
308
309 for (size_t i = 0; i < num_buffers; i++) {
310 hBufs[i].streamId =
311 static_cast<Camera3Stream*>(buffers[i]->stream)->mId;
312 hBufs[i].buffer = nullptr; // use bufferId
313 hBufs[i].bufferId = popBufferId(*(buffers[i]->buffer), hBufs[i].streamId);
314 if (hBufs[i].bufferId == BUFFER_ID_NO_BUFFER) {
315 ALOGE("%s: unknown buffer is returned to stream %d",
316 __FUNCTION__, hBufs[i].streamId);
317 }
318 // ERROR since the buffer is not for application to consume
319 hBufs[i].status = BufferStatus::ERROR;
320 // skip acquire fence since it's of no use to camera service
321 if (buffers[i]->release_fence != -1) {
322 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
323 handle->data[0] = buffers[i]->release_fence;
324 hBufs[i].releaseFence.setTo(handle, /*shouldOwn*/true);
325 }
326 }
327
328 mCallback_3_5->returnStreamBuffers(hBufs);
329 return;
330}
331
332/**
333 * Static callback forwarding methods from HAL to instance
334 */
335camera3_buffer_request_status_t CameraDeviceSession::sRequestStreamBuffers(
336 const struct camera3_callback_ops *cb,
337 uint32_t num_buffer_reqs,
338 const camera3_buffer_request_t *buffer_reqs,
339 /*out*/uint32_t *num_returned_buf_reqs,
340 /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
341 CameraDeviceSession *d =
342 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
343
344 if (num_buffer_reqs == 0 || buffer_reqs == nullptr || num_returned_buf_reqs == nullptr ||
345 returned_buf_reqs == nullptr) {
346 ALOGE("%s: bad argument: numBufReq %d, bufReqs %p, numRetBufReq %p, retBufReqs %p",
347 __FUNCTION__, num_buffer_reqs, buffer_reqs,
348 num_returned_buf_reqs, returned_buf_reqs);
349 return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
350 }
351
352 return d->requestStreamBuffers(num_buffer_reqs, buffer_reqs,
353 num_returned_buf_reqs, returned_buf_reqs);
354}
355
356void CameraDeviceSession::sReturnStreamBuffers(
357 const struct camera3_callback_ops *cb,
358 uint32_t num_buffers,
359 const camera3_stream_buffer_t* const* buffers) {
360 CameraDeviceSession *d =
361 const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
362
363 d->returnStreamBuffers(num_buffers, buffers);
364}
365
Emilian Peev22eac5f2019-01-23 11:14:11 -0800366Return<void> CameraDeviceSession::isReconfigurationRequired(
367 const V3_2::CameraMetadata& oldSessionParams, const V3_2::CameraMetadata& newSessionParams,
368 ICameraDeviceSession::isReconfigurationRequired_cb _hidl_cb) {
369 if (mDevice->ops->is_reconfiguration_required != nullptr) {
370 const camera_metadata_t *oldParams, *newParams;
371 V3_2::implementation::convertFromHidl(oldSessionParams, &oldParams);
372 V3_2::implementation::convertFromHidl(newSessionParams, &newParams);
373 auto ret = mDevice->ops->is_reconfiguration_required(mDevice, oldParams, newParams);
374 switch (ret) {
375 case 0:
376 _hidl_cb(Status::OK, true);
377 break;
378 case -EINVAL:
379 _hidl_cb(Status::OK, false);
380 break;
381 case -ENOSYS:
382 _hidl_cb(Status::METHOD_NOT_SUPPORTED, true);
383 break;
384 default:
385 _hidl_cb(Status::INTERNAL_ERROR, true);
386 break;
387 };
388 } else {
389 _hidl_cb(Status::METHOD_NOT_SUPPORTED, true);
390 }
391
392 return Void();
393}
394
Yin-Chia Yeh6a6fe0f2018-09-06 15:38:34 -0700395} // namespace implementation
396} // namespace V3_5
397} // namespace device
398} // namespace camera
399} // namespace hardware
400} // namespace android