1 /*
2 * Copyright (C) 2019 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 "android.hardware.automotive.evs@1.1-service"
18
19 #include "EvsCamera.h"
20 #include "EvsEnumerator.h"
21
22 #include <ui/GraphicBufferAllocator.h>
23 #include <ui/GraphicBufferMapper.h>
24 #include <utils/SystemClock.h>
25
26 namespace android {
27 namespace hardware {
28 namespace automotive {
29 namespace evs {
30 namespace V1_1 {
31 namespace implementation {
32
33
34 // Special camera names for which we'll initialize alternate test data
35 const char EvsCamera::kCameraName_Backup[] = "backup";
36
37
38 // Arbitrary limit on number of graphics buffers allowed to be allocated
39 // Safeguards against unreasonable resource consumption and provides a testable limit
40 const unsigned MAX_BUFFERS_IN_FLIGHT = 100;
41
42
EvsCamera(const char * id,unique_ptr<ConfigManager::CameraInfo> & camInfo)43 EvsCamera::EvsCamera(const char *id,
44 unique_ptr<ConfigManager::CameraInfo> &camInfo) :
45 mFramesAllowed(0),
46 mFramesInUse(0),
47 mStreamState(STOPPED),
48 mCameraInfo(camInfo) {
49
50 ALOGD("EvsCamera instantiated");
51
52 /* set a camera id */
53 mDescription.v1.cameraId = id;
54
55 /* set camera metadata */
56 mDescription.metadata.setToExternal((uint8_t *)camInfo->characteristics,
57 get_camera_metadata_size(camInfo->characteristics));
58 }
59
60
~EvsCamera()61 EvsCamera::~EvsCamera() {
62 ALOGD("EvsCamera being destroyed");
63 forceShutdown();
64 }
65
66
67 //
68 // This gets called if another caller "steals" ownership of the camera
69 //
forceShutdown()70 void EvsCamera::forceShutdown()
71 {
72 ALOGD("EvsCamera forceShutdown");
73
74 // Make sure our output stream is cleaned up
75 // (It really should be already)
76 stopVideoStream();
77
78 // Claim the lock while we work on internal state
79 std::lock_guard <std::mutex> lock(mAccessLock);
80
81 // Drop all the graphics buffers we've been using
82 if (mBuffers.size() > 0) {
83 GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
84 for (auto&& rec : mBuffers) {
85 if (rec.inUse) {
86 ALOGE("Error - releasing buffer despite remote ownership");
87 }
88 alloc.free(rec.handle);
89 rec.handle = nullptr;
90 }
91 mBuffers.clear();
92 }
93
94 // Put this object into an unrecoverable error state since somebody else
95 // is going to own the underlying camera now
96 mStreamState = DEAD;
97 }
98
99
100 // Methods from ::android::hardware::automotive::evs::V1_0::IEvsCamera follow.
getCameraInfo(getCameraInfo_cb _hidl_cb)101 Return<void> EvsCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
102 ALOGD("getCameraInfo");
103
104 // Send back our self description
105 _hidl_cb(mDescription.v1);
106 return Void();
107 }
108
109
setMaxFramesInFlight(uint32_t bufferCount)110 Return<EvsResult> EvsCamera::setMaxFramesInFlight(uint32_t bufferCount) {
111 ALOGD("setMaxFramesInFlight");
112 std::lock_guard<std::mutex> lock(mAccessLock);
113
114 // If we've been displaced by another owner of the camera, then we can't do anything else
115 if (mStreamState == DEAD) {
116 ALOGE("ignoring setMaxFramesInFlight call when camera has been lost.");
117 return EvsResult::OWNERSHIP_LOST;
118 }
119
120 // We cannot function without at least one video buffer to send data
121 if (bufferCount < 1) {
122 ALOGE("Ignoring setMaxFramesInFlight with less than one buffer requested");
123 return EvsResult::INVALID_ARG;
124 }
125
126 // Update our internal state
127 if (setAvailableFrames_Locked(bufferCount)) {
128 return EvsResult::OK;
129 } else {
130 return EvsResult::BUFFER_NOT_AVAILABLE;
131 }
132 }
133
134
startVideoStream(const::android::sp<IEvsCameraStream_1_0> & stream)135 Return<EvsResult> EvsCamera::startVideoStream(const ::android::sp<IEvsCameraStream_1_0>& stream) {
136 ALOGD("startVideoStream");
137 std::lock_guard<std::mutex> lock(mAccessLock);
138
139 // If we've been displaced by another owner of the camera, then we can't do anything else
140 if (mStreamState == DEAD) {
141 ALOGE("ignoring startVideoStream call when camera has been lost.");
142 return EvsResult::OWNERSHIP_LOST;
143 }
144 if (mStreamState != STOPPED) {
145 ALOGE("ignoring startVideoStream call when a stream is already running.");
146 return EvsResult::STREAM_ALREADY_RUNNING;
147 }
148
149 // If the client never indicated otherwise, configure ourselves for a single streaming buffer
150 if (mFramesAllowed < 1) {
151 if (!setAvailableFrames_Locked(1)) {
152 ALOGE("Failed to start stream because we couldn't get a graphics buffer");
153 return EvsResult::BUFFER_NOT_AVAILABLE;
154 }
155 }
156
157 // Record the user's callback for use when we have a frame ready
158 mStream = IEvsCameraStream_1_1::castFrom(stream).withDefault(nullptr);
159 if (mStream == nullptr) {
160 ALOGE("Default implementation does not support v1.0 IEvsCameraStream");
161 return EvsResult::INVALID_ARG;
162 }
163
164 // Start the frame generation thread
165 mStreamState = RUNNING;
166 mCaptureThread = std::thread([this](){ generateFrames(); });
167
168 return EvsResult::OK;
169 }
170
171
doneWithFrame(const BufferDesc_1_0 & buffer)172 Return<void> EvsCamera::doneWithFrame(const BufferDesc_1_0& buffer) {
173 std::lock_guard <std::mutex> lock(mAccessLock);
174 returnBuffer(buffer.bufferId, buffer.memHandle);
175
176 return Void();
177 }
178
179
stopVideoStream()180 Return<void> EvsCamera::stopVideoStream() {
181 ALOGD("stopVideoStream");
182 std::unique_lock <std::mutex> lock(mAccessLock);
183
184 if (mStreamState == RUNNING) {
185 // Tell the GenerateFrames loop we want it to stop
186 mStreamState = STOPPING;
187
188 // Block outside the mutex until the "stop" flag has been acknowledged
189 // We won't send any more frames, but the client might still get some already in flight
190 ALOGD("Waiting for stream thread to end...");
191 lock.unlock();
192 mCaptureThread.join();
193 lock.lock();
194
195 mStreamState = STOPPED;
196 mStream = nullptr;
197 ALOGD("Stream marked STOPPED.");
198 }
199
200 return Void();
201 }
202
203
getExtendedInfo(uint32_t opaqueIdentifier)204 Return<int32_t> EvsCamera::getExtendedInfo(uint32_t opaqueIdentifier) {
205 ALOGD("getExtendedInfo");
206 std::lock_guard<std::mutex> lock(mAccessLock);
207
208 // For any single digit value, return the index itself as a test value
209 if (opaqueIdentifier <= 9) {
210 return opaqueIdentifier;
211 }
212
213 // Return zero by default as required by the spec
214 return 0;
215 }
216
217
setExtendedInfo(uint32_t,int32_t)218 Return<EvsResult> EvsCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/, int32_t /*opaqueValue*/) {
219 ALOGD("setExtendedInfo");
220 std::lock_guard<std::mutex> lock(mAccessLock);
221
222 // If we've been displaced by another owner of the camera, then we can't do anything else
223 if (mStreamState == DEAD) {
224 ALOGE("ignoring setExtendedInfo call when camera has been lost.");
225 return EvsResult::OWNERSHIP_LOST;
226 }
227
228 // We don't store any device specific information in this implementation
229 return EvsResult::INVALID_ARG;
230 }
231
232
233 // Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb)234 Return<void> EvsCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb _hidl_cb) {
235 ALOGD("getCameraInfo_1_1");
236
237 // Send back our self description
238 _hidl_cb(mDescription);
239 return Void();
240 }
241
242
getPhysicalCameraInfo(const hidl_string & id,getCameraInfo_1_1_cb _hidl_cb)243 Return<void> EvsCamera::getPhysicalCameraInfo(const hidl_string& id,
244 getCameraInfo_1_1_cb _hidl_cb) {
245 ALOGD("%s", __FUNCTION__);
246
247 // This works exactly same as getCameraInfo_1_1() in default implementation.
248 (void)id;
249 _hidl_cb(mDescription);
250 return Void();
251 }
252
253
doneWithFrame_1_1(const hidl_vec<BufferDesc_1_1> & buffers)254 Return<EvsResult> EvsCamera::doneWithFrame_1_1(const hidl_vec<BufferDesc_1_1>& buffers) {
255 std::lock_guard <std::mutex> lock(mAccessLock);
256
257 for (auto&& buffer : buffers) {
258 returnBuffer(buffer.bufferId, buffer.buffer.nativeHandle);
259 }
260
261 return EvsResult::OK;
262 }
263
264
pauseVideoStream()265 Return<EvsResult> EvsCamera::pauseVideoStream() {
266 // Default implementation does not support this.
267 return EvsResult::UNDERLYING_SERVICE_ERROR;
268 }
269
270
resumeVideoStream()271 Return<EvsResult> EvsCamera::resumeVideoStream() {
272 // Default implementation does not support this.
273 return EvsResult::UNDERLYING_SERVICE_ERROR;
274 }
275
276
setMaster()277 Return<EvsResult> EvsCamera::setMaster() {
278 // Default implementation does not expect multiple subscribers and therefore
279 // return a success code always.
280 return EvsResult::OK;
281 }
282
forceMaster(const sp<IEvsDisplay_1_0> &)283 Return<EvsResult> EvsCamera::forceMaster(const sp<IEvsDisplay_1_0>& ) {
284 // Default implementation does not expect multiple subscribers and therefore
285 // return a success code always.
286 return EvsResult::OK;
287 }
288
289
unsetMaster()290 Return<EvsResult> EvsCamera::unsetMaster() {
291 // Default implementation does not expect multiple subscribers and therefore
292 // return a success code always.
293 return EvsResult::OK;
294 }
295
296
getParameterList(getParameterList_cb _hidl_cb)297 Return<void> EvsCamera::getParameterList(getParameterList_cb _hidl_cb) {
298 hidl_vec<CameraParam> hidlCtrls;
299 hidlCtrls.resize(mCameraInfo->controls.size());
300 unsigned idx = 0;
301 for (auto& [cid, cfg] : mCameraInfo->controls) {
302 hidlCtrls[idx++] = cid;
303 }
304
305 _hidl_cb(hidlCtrls);
306 return Void();
307 }
308
309
getIntParameterRange(CameraParam id,getIntParameterRange_cb _hidl_cb)310 Return<void> EvsCamera::getIntParameterRange(CameraParam id,
311 getIntParameterRange_cb _hidl_cb) {
312 auto range = mCameraInfo->controls[id];
313 _hidl_cb(get<0>(range), get<1>(range), get<2>(range));
314 return Void();
315 }
316
317
setIntParameter(CameraParam id,int32_t value,setIntParameter_cb _hidl_cb)318 Return<void> EvsCamera::setIntParameter(CameraParam id, int32_t value,
319 setIntParameter_cb _hidl_cb) {
320 // Default implementation does not support this.
321 (void)id;
322 (void)value;
323 _hidl_cb(EvsResult::INVALID_ARG, 0);
324 return Void();
325 }
326
327
getIntParameter(CameraParam id,getIntParameter_cb _hidl_cb)328 Return<void> EvsCamera::getIntParameter(CameraParam id,
329 getIntParameter_cb _hidl_cb) {
330 // Default implementation does not support this.
331 (void)id;
332 _hidl_cb(EvsResult::INVALID_ARG, 0);
333 return Void();
334 }
335
336
setExtendedInfo_1_1(uint32_t opaqueIdentifier,const hidl_vec<uint8_t> & opaqueValue)337 Return<EvsResult> EvsCamera::setExtendedInfo_1_1(uint32_t opaqueIdentifier,
338 const hidl_vec<uint8_t>& opaqueValue) {
339 // Default implementation does not use an extended info.
340 (void)opaqueIdentifier;
341 (void)opaqueValue;
342 return EvsResult::INVALID_ARG;
343 }
344
345
getExtendedInfo_1_1(uint32_t opaqueIdentifier,getExtendedInfo_1_1_cb _hidl_cb)346 Return<void> EvsCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
347 getExtendedInfo_1_1_cb _hidl_cb) {
348 // Default implementation does not use an extended info.
349 (void)opaqueIdentifier;
350
351 hidl_vec<uint8_t> value;
352 _hidl_cb(EvsResult::INVALID_ARG, value);
353 return Void();
354 }
355
356
357 Return<void>
importExternalBuffers(const hidl_vec<BufferDesc_1_1> &,importExternalBuffers_cb _hidl_cb)358 EvsCamera::importExternalBuffers(const hidl_vec<BufferDesc_1_1>& /* buffers */,
359 importExternalBuffers_cb _hidl_cb) {
360 ALOGW("%s is not implemented yet.", __FUNCTION__);
361 _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
362 return {};
363 }
364
365
setAvailableFrames_Locked(unsigned bufferCount)366 bool EvsCamera::setAvailableFrames_Locked(unsigned bufferCount) {
367 if (bufferCount < 1) {
368 ALOGE("Ignoring request to set buffer count to zero");
369 return false;
370 }
371 if (bufferCount > MAX_BUFFERS_IN_FLIGHT) {
372 ALOGE("Rejecting buffer request in excess of internal limit");
373 return false;
374 }
375
376 // Is an increase required?
377 if (mFramesAllowed < bufferCount) {
378 // An increase is required
379 unsigned needed = bufferCount - mFramesAllowed;
380 ALOGI("Allocating %d buffers for camera frames", needed);
381
382 unsigned added = increaseAvailableFrames_Locked(needed);
383 if (added != needed) {
384 // If we didn't add all the frames we needed, then roll back to the previous state
385 ALOGE("Rolling back to previous frame queue size");
386 decreaseAvailableFrames_Locked(added);
387 return false;
388 }
389 } else if (mFramesAllowed > bufferCount) {
390 // A decrease is required
391 unsigned framesToRelease = mFramesAllowed - bufferCount;
392 ALOGI("Returning %d camera frame buffers", framesToRelease);
393
394 unsigned released = decreaseAvailableFrames_Locked(framesToRelease);
395 if (released != framesToRelease) {
396 // This shouldn't happen with a properly behaving client because the client
397 // should only make this call after returning sufficient outstanding buffers
398 // to allow a clean resize.
399 ALOGE("Buffer queue shrink failed -- too many buffers currently in use?");
400 }
401 }
402
403 return true;
404 }
405
406
increaseAvailableFrames_Locked(unsigned numToAdd)407 unsigned EvsCamera::increaseAvailableFrames_Locked(unsigned numToAdd) {
408 // Acquire the graphics buffer allocator
409 GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
410
411 unsigned added = 0;
412
413 while (added < numToAdd) {
414 buffer_handle_t memHandle = nullptr;
415 status_t result = alloc.allocate(mWidth, mHeight, mFormat, 1, mUsage,
416 &memHandle, &mStride, 0, "EvsCamera");
417 if (result != NO_ERROR) {
418 ALOGE("Error %d allocating %d x %d graphics buffer", result, mWidth, mHeight);
419 break;
420 }
421 if (!memHandle) {
422 ALOGE("We didn't get a buffer handle back from the allocator");
423 break;
424 }
425
426 // Find a place to store the new buffer
427 bool stored = false;
428 for (auto&& rec : mBuffers) {
429 if (rec.handle == nullptr) {
430 // Use this existing entry
431 rec.handle = memHandle;
432 rec.inUse = false;
433 stored = true;
434 break;
435 }
436 }
437 if (!stored) {
438 // Add a BufferRecord wrapping this handle to our set of available buffers
439 mBuffers.emplace_back(memHandle);
440 }
441
442 mFramesAllowed++;
443 added++;
444 }
445
446 return added;
447 }
448
449
decreaseAvailableFrames_Locked(unsigned numToRemove)450 unsigned EvsCamera::decreaseAvailableFrames_Locked(unsigned numToRemove) {
451 // Acquire the graphics buffer allocator
452 GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
453
454 unsigned removed = 0;
455
456 for (auto&& rec : mBuffers) {
457 // Is this record not in use, but holding a buffer that we can free?
458 if ((rec.inUse == false) && (rec.handle != nullptr)) {
459 // Release buffer and update the record so we can recognize it as "empty"
460 alloc.free(rec.handle);
461 rec.handle = nullptr;
462
463 mFramesAllowed--;
464 removed++;
465
466 if (removed == numToRemove) {
467 break;
468 }
469 }
470 }
471
472 return removed;
473 }
474
475
476 // This is the asynchronous frame generation thread that runs in parallel with the
477 // main serving thread. There is one for each active camera instance.
generateFrames()478 void EvsCamera::generateFrames() {
479 ALOGD("Frame generation loop started");
480
481 unsigned idx;
482
483 while (true) {
484 bool timeForFrame = false;
485 nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
486
487 // Lock scope for updating shared state
488 {
489 std::lock_guard<std::mutex> lock(mAccessLock);
490
491 if (mStreamState != RUNNING) {
492 // Break out of our main thread loop
493 break;
494 }
495
496 // Are we allowed to issue another buffer?
497 if (mFramesInUse >= mFramesAllowed) {
498 // Can't do anything right now -- skip this frame
499 ALOGW("Skipped a frame because too many are in flight\n");
500 } else {
501 // Identify an available buffer to fill
502 for (idx = 0; idx < mBuffers.size(); idx++) {
503 if (!mBuffers[idx].inUse) {
504 if (mBuffers[idx].handle != nullptr) {
505 // Found an available record, so stop looking
506 break;
507 }
508 }
509 }
510 if (idx >= mBuffers.size()) {
511 // This shouldn't happen since we already checked mFramesInUse vs mFramesAllowed
512 ALOGE("Failed to find an available buffer slot\n");
513 } else {
514 // We're going to make the frame busy
515 mBuffers[idx].inUse = true;
516 mFramesInUse++;
517 timeForFrame = true;
518 }
519 }
520 }
521
522 if (timeForFrame) {
523 // Assemble the buffer description we'll transmit below
524 BufferDesc_1_1 newBuffer = {};
525 AHardwareBuffer_Desc* pDesc =
526 reinterpret_cast<AHardwareBuffer_Desc *>(&newBuffer.buffer.description);
527 pDesc->width = mWidth;
528 pDesc->height = mHeight;
529 pDesc->layers = 1;
530 pDesc->format = mFormat;
531 pDesc->usage = mUsage;
532 pDesc->stride = mStride;
533 newBuffer.buffer.nativeHandle = mBuffers[idx].handle;
534 newBuffer.pixelSize = sizeof(uint32_t);
535 newBuffer.bufferId = idx;
536 newBuffer.deviceId = mDescription.v1.cameraId;
537 newBuffer.timestamp = elapsedRealtimeNano();
538
539 // Write test data into the image buffer
540 fillTestFrame(newBuffer);
541
542 // Issue the (asynchronous) callback to the client -- can't be holding the lock
543 hidl_vec<BufferDesc_1_1> frames;
544 frames.resize(1);
545 frames[0] = newBuffer;
546 auto result = mStream->deliverFrame_1_1(frames);
547 if (result.isOk()) {
548 ALOGD("Delivered %p as id %d",
549 newBuffer.buffer.nativeHandle.getNativeHandle(), newBuffer.bufferId);
550 } else {
551 // This can happen if the client dies and is likely unrecoverable.
552 // To avoid consuming resources generating failing calls, we stop sending
553 // frames. Note, however, that the stream remains in the "STREAMING" state
554 // until cleaned up on the main thread.
555 ALOGE("Frame delivery call failed in the transport layer.");
556
557 // Since we didn't actually deliver it, mark the frame as available
558 std::lock_guard<std::mutex> lock(mAccessLock);
559 mBuffers[idx].inUse = false;
560 mFramesInUse--;
561
562 break;
563 }
564 }
565
566 // We arbitrarily choose to generate frames at 12 fps to ensure we pass the 10fps test requirement
567 static const int kTargetFrameRate = 12;
568 static const nsecs_t kTargetFrameTimeUs = 1000*1000 / kTargetFrameRate;
569 const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
570 const nsecs_t workTimeUs = (now - startTime) / 1000;
571 const nsecs_t sleepDurationUs = kTargetFrameTimeUs - workTimeUs;
572 if (sleepDurationUs > 0) {
573 usleep(sleepDurationUs);
574 }
575 }
576
577 // If we've been asked to stop, send an event to signal the actual end of stream
578 EvsEventDesc event;
579 event.aType = EvsEventType::STREAM_STOPPED;
580 auto result = mStream->notify(event);
581 if (!result.isOk()) {
582 ALOGE("Error delivering end of stream marker");
583 }
584
585 return;
586 }
587
588
fillTestFrame(const BufferDesc_1_1 & buff)589 void EvsCamera::fillTestFrame(const BufferDesc_1_1& buff) {
590 // Lock our output buffer for writing
591 uint32_t *pixels = nullptr;
592 const AHardwareBuffer_Desc* pDesc =
593 reinterpret_cast<const AHardwareBuffer_Desc *>(&buff.buffer.description);
594 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
595 mapper.lock(buff.buffer.nativeHandle,
596 GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER,
597 android::Rect(pDesc->width, pDesc->height),
598 (void **) &pixels);
599
600 // If we failed to lock the pixel buffer, we're about to crash, but log it first
601 if (!pixels) {
602 ALOGE("Camera failed to gain access to image buffer for writing");
603 }
604
605 // Fill in the test pixels
606 for (unsigned row = 0; row < pDesc->height; row++) {
607 for (unsigned col = 0; col < pDesc->width; col++) {
608 // Index into the row to check the pixel at this column.
609 // We expect 0xFF in the LSB channel, a vertical gradient in the
610 // second channel, a horitzontal gradient in the third channel, and
611 // 0xFF in the MSB.
612 // The exception is the very first 32 bits which is used for the
613 // time varying frame signature to avoid getting fooled by a static image.
614 uint32_t expectedPixel = 0xFF0000FF | // MSB and LSB
615 ((row & 0xFF) << 8) | // vertical gradient
616 ((col & 0xFF) << 16); // horizontal gradient
617 if ((row | col) == 0) {
618 static uint32_t sFrameTicker = 0;
619 expectedPixel = (sFrameTicker) & 0xFF;
620 sFrameTicker++;
621 }
622 pixels[col] = expectedPixel;
623 }
624 // Point to the next row
625 // NOTE: stride retrieved from gralloc is in units of pixels
626 pixels = pixels + pDesc->stride;
627 }
628
629 // Release our output buffer
630 mapper.unlock(buff.buffer.nativeHandle);
631 }
632
633
fillTestFrame(const BufferDesc_1_0 & buff)634 void EvsCamera::fillTestFrame(const BufferDesc_1_0& buff) {
635 BufferDesc_1_1 newBufDesc = {};
636 AHardwareBuffer_Desc desc = {
637 buff.width, // width
638 buff.height, // height
639 1, // layers, always 1 for EVS
640 buff.format, // One of AHardwareBuffer_Format
641 buff.usage, // Combination of AHardwareBuffer_UsageFlags
642 buff.stride, // Row stride in pixels
643 0, // Reserved
644 0 // Reserved
645 };
646 memcpy(&desc, &newBufDesc.buffer.description, sizeof(desc));
647 newBufDesc.buffer.nativeHandle = buff.memHandle;
648 newBufDesc.pixelSize = buff.pixelSize;
649 newBufDesc.bufferId = buff.bufferId;
650
651 return fillTestFrame(newBufDesc);
652 }
653
654
returnBuffer(const uint32_t bufferId,const buffer_handle_t memHandle)655 void EvsCamera::returnBuffer(const uint32_t bufferId, const buffer_handle_t memHandle) {
656 std::lock_guard <std::mutex> lock(mAccessLock);
657
658 if (memHandle == nullptr) {
659 ALOGE("ignoring doneWithFrame called with null handle");
660 } else if (bufferId >= mBuffers.size()) {
661 ALOGE("ignoring doneWithFrame called with invalid bufferId %d (max is %zu)",
662 bufferId, mBuffers.size()-1);
663 } else if (!mBuffers[bufferId].inUse) {
664 ALOGE("ignoring doneWithFrame called on frame %d which is already free",
665 bufferId);
666 } else {
667 // Mark the frame as available
668 mBuffers[bufferId].inUse = false;
669 mFramesInUse--;
670
671 // If this frame's index is high in the array, try to move it down
672 // to improve locality after mFramesAllowed has been reduced.
673 if (bufferId >= mFramesAllowed) {
674 // Find an empty slot lower in the array (which should always exist in this case)
675 for (auto&& rec : mBuffers) {
676 if (rec.handle == nullptr) {
677 rec.handle = mBuffers[bufferId].handle;
678 mBuffers[bufferId].handle = nullptr;
679 break;
680 }
681 }
682 }
683 }
684 }
685
686
Create(const char * deviceName)687 sp<EvsCamera> EvsCamera::Create(const char *deviceName) {
688 unique_ptr<ConfigManager::CameraInfo> nullCamInfo = nullptr;
689
690 return Create(deviceName, nullCamInfo);
691 }
692
693
Create(const char * deviceName,unique_ptr<ConfigManager::CameraInfo> & camInfo,const Stream * streamCfg)694 sp<EvsCamera> EvsCamera::Create(const char *deviceName,
695 unique_ptr<ConfigManager::CameraInfo> &camInfo,
696 const Stream *streamCfg) {
697 sp<EvsCamera> evsCamera = new EvsCamera(deviceName, camInfo);
698 if (evsCamera == nullptr) {
699 return nullptr;
700 }
701
702 /* default implementation does not use a given configuration */
703 (void)streamCfg;
704
705 /* Use the first resolution from the list for the testing */
706 auto it = camInfo->streamConfigurations.begin();
707 evsCamera->mWidth = it->second[1];
708 evsCamera->mHeight = it->second[2];
709 evsCamera->mDescription.v1.vendorFlags = 0xFFFFFFFF; // Arbitrary test value
710
711 evsCamera->mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
712 evsCamera->mUsage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE |
713 GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
714
715 return evsCamera;
716 }
717
718
719 } // namespace implementation
720 } // namespace V1_0
721 } // namespace evs
722 } // namespace automotive
723 } // namespace hardware
724 } // namespace android
725