blob: 5ba753da2ecf25f0e5eeea3e2f7a82c43fb6bcb8 [file] [log] [blame]
Changyeon Jo2400b692019-07-18 21:32:48 -07001/*
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
25
26namespace android {
27namespace hardware {
28namespace automotive {
29namespace evs {
30namespace V1_1 {
31namespace implementation {
32
33
34// Special camera names for which we'll initialize alternate test data
35const 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
40const unsigned MAX_BUFFERS_IN_FLIGHT = 100;
41
42
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070043EvsCamera::EvsCamera(const char *id,
44 unique_ptr<ConfigManager::CameraInfo> &camInfo) :
Changyeon Jo2400b692019-07-18 21:32:48 -070045 mFramesAllowed(0),
46 mFramesInUse(0),
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070047 mStreamState(STOPPED),
48 mCameraInfo(camInfo) {
Changyeon Jo2400b692019-07-18 21:32:48 -070049
50 ALOGD("EvsCamera instantiated");
51
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070052 /* set a camera id */
53 mDescription.v1.cameraId = id;
Changyeon Jo2400b692019-07-18 21:32:48 -070054
Changyeon Joc6fa0ab2019-10-12 05:25:44 -070055 /* set camera metadata */
56 mDescription.metadata.setToExternal((uint8_t *)camInfo->characteristics,
57 get_camera_metadata_size(camInfo->characteristics));
Changyeon Jo2400b692019-07-18 21:32:48 -070058}
59
60
61EvsCamera::~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//
70void 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.
101Return<void> EvsCamera::getCameraInfo(getCameraInfo_cb _hidl_cb) {
102 ALOGD("getCameraInfo");
103
104 // Send back our self description
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700105 _hidl_cb(mDescription.v1);
Changyeon Jo2400b692019-07-18 21:32:48 -0700106 return Void();
107}
108
109
110Return<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
135Return<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
172Return<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
180Return<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
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700190 ALOGD("Waiting for stream thread to end...");
Changyeon Jo2400b692019-07-18 21:32:48 -0700191 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
204Return<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
218Return<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.
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700234Return<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
Changyeon Jo2400b692019-07-18 21:32:48 -0700243Return<EvsResult> EvsCamera::doneWithFrame_1_1(const BufferDesc_1_1& bufDesc) {
244 std::lock_guard <std::mutex> lock(mAccessLock);
245 returnBuffer(bufDesc.bufferId, bufDesc.buffer.nativeHandle);
246
247 return EvsResult::OK;
248}
249
250
251Return<EvsResult> EvsCamera::pauseVideoStream() {
252 // Default implementation does not support this.
253 return EvsResult::UNDERLYING_SERVICE_ERROR;
254}
255
256
257Return<EvsResult> EvsCamera::resumeVideoStream() {
258 // Default implementation does not support this.
259 return EvsResult::UNDERLYING_SERVICE_ERROR;
260}
261
262
Changyeon Jod2a82462019-07-30 11:57:17 -0700263Return<EvsResult> EvsCamera::setMaster() {
264 // Default implementation does not expect multiple subscribers and therefore
265 // return a success code always.
266 return EvsResult::OK;
267}
268
Changyeon Jo0d0228d2019-08-17 21:40:28 -0700269Return<EvsResult> EvsCamera::forceMaster(const sp<IEvsDisplay>& ) {
270 // Default implementation does not expect multiple subscribers and therefore
271 // return a success code always.
272 return EvsResult::OK;
273}
274
Changyeon Jod2a82462019-07-30 11:57:17 -0700275
276Return<EvsResult> EvsCamera::unsetMaster() {
277 // Default implementation does not expect multiple subscribers and therefore
278 // return a success code always.
279 return EvsResult::OK;
280}
281
282
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700283Return<void> EvsCamera::getParameterList(getParameterList_cb _hidl_cb) {
284 hidl_vec<CameraParam> hidlCtrls;
285 hidlCtrls.resize(mCameraInfo->controls.size());
286 unsigned idx = 0;
287 for (auto& [cid, cfg] : mCameraInfo->controls) {
288 hidlCtrls[idx++] = cid;
289 }
290
291 _hidl_cb(hidlCtrls);
292 return Void();
293}
294
295
296Return<void> EvsCamera::getIntParameterRange(CameraParam id,
297 getIntParameterRange_cb _hidl_cb) {
298 auto range = mCameraInfo->controls[id];
299 _hidl_cb(get<0>(range), get<1>(range), get<2>(range));
300 return Void();
301}
302
303
304Return<void> EvsCamera::setIntParameter(CameraParam id, int32_t value,
305 setIntParameter_cb _hidl_cb) {
Changyeon Jod2a82462019-07-30 11:57:17 -0700306 // Default implementation does not support this.
307 (void)id;
308 (void)value;
309 _hidl_cb(EvsResult::INVALID_ARG, 0);
310 return Void();
311}
312
313
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700314Return<void> EvsCamera::getIntParameter(CameraParam id,
315 getIntParameter_cb _hidl_cb) {
Changyeon Jod2a82462019-07-30 11:57:17 -0700316 // Default implementation does not support this.
317 (void)id;
318 _hidl_cb(EvsResult::INVALID_ARG, 0);
319 return Void();
320}
321
322
Changyeon Jo2400b692019-07-18 21:32:48 -0700323bool EvsCamera::setAvailableFrames_Locked(unsigned bufferCount) {
324 if (bufferCount < 1) {
325 ALOGE("Ignoring request to set buffer count to zero");
326 return false;
327 }
328 if (bufferCount > MAX_BUFFERS_IN_FLIGHT) {
329 ALOGE("Rejecting buffer request in excess of internal limit");
330 return false;
331 }
332
333 // Is an increase required?
334 if (mFramesAllowed < bufferCount) {
335 // An increase is required
336 unsigned needed = bufferCount - mFramesAllowed;
337 ALOGI("Allocating %d buffers for camera frames", needed);
338
339 unsigned added = increaseAvailableFrames_Locked(needed);
340 if (added != needed) {
341 // If we didn't add all the frames we needed, then roll back to the previous state
342 ALOGE("Rolling back to previous frame queue size");
343 decreaseAvailableFrames_Locked(added);
344 return false;
345 }
346 } else if (mFramesAllowed > bufferCount) {
347 // A decrease is required
348 unsigned framesToRelease = mFramesAllowed - bufferCount;
349 ALOGI("Returning %d camera frame buffers", framesToRelease);
350
351 unsigned released = decreaseAvailableFrames_Locked(framesToRelease);
352 if (released != framesToRelease) {
353 // This shouldn't happen with a properly behaving client because the client
354 // should only make this call after returning sufficient outstanding buffers
355 // to allow a clean resize.
356 ALOGE("Buffer queue shrink failed -- too many buffers currently in use?");
357 }
358 }
359
360 return true;
361}
362
363
364unsigned EvsCamera::increaseAvailableFrames_Locked(unsigned numToAdd) {
365 // Acquire the graphics buffer allocator
366 GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
367
368 unsigned added = 0;
369
370 while (added < numToAdd) {
371 buffer_handle_t memHandle = nullptr;
372 status_t result = alloc.allocate(mWidth, mHeight, mFormat, 1, mUsage,
373 &memHandle, &mStride, 0, "EvsCamera");
374 if (result != NO_ERROR) {
375 ALOGE("Error %d allocating %d x %d graphics buffer", result, mWidth, mHeight);
376 break;
377 }
378 if (!memHandle) {
379 ALOGE("We didn't get a buffer handle back from the allocator");
380 break;
381 }
382
383 // Find a place to store the new buffer
384 bool stored = false;
385 for (auto&& rec : mBuffers) {
386 if (rec.handle == nullptr) {
387 // Use this existing entry
388 rec.handle = memHandle;
389 rec.inUse = false;
390 stored = true;
391 break;
392 }
393 }
394 if (!stored) {
395 // Add a BufferRecord wrapping this handle to our set of available buffers
396 mBuffers.emplace_back(memHandle);
397 }
398
399 mFramesAllowed++;
400 added++;
401 }
402
403 return added;
404}
405
406
407unsigned EvsCamera::decreaseAvailableFrames_Locked(unsigned numToRemove) {
408 // Acquire the graphics buffer allocator
409 GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
410
411 unsigned removed = 0;
412
413 for (auto&& rec : mBuffers) {
414 // Is this record not in use, but holding a buffer that we can free?
415 if ((rec.inUse == false) && (rec.handle != nullptr)) {
416 // Release buffer and update the record so we can recognize it as "empty"
417 alloc.free(rec.handle);
418 rec.handle = nullptr;
419
420 mFramesAllowed--;
421 removed++;
422
423 if (removed == numToRemove) {
424 break;
425 }
426 }
427 }
428
429 return removed;
430}
431
432
433// This is the asynchronous frame generation thread that runs in parallel with the
434// main serving thread. There is one for each active camera instance.
435void EvsCamera::generateFrames() {
436 ALOGD("Frame generation loop started");
437
438 unsigned idx;
439
440 while (true) {
441 bool timeForFrame = false;
442 nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
443
444 // Lock scope for updating shared state
445 {
446 std::lock_guard<std::mutex> lock(mAccessLock);
447
448 if (mStreamState != RUNNING) {
449 // Break out of our main thread loop
450 break;
451 }
452
453 // Are we allowed to issue another buffer?
454 if (mFramesInUse >= mFramesAllowed) {
455 // Can't do anything right now -- skip this frame
456 ALOGW("Skipped a frame because too many are in flight\n");
457 } else {
458 // Identify an available buffer to fill
459 for (idx = 0; idx < mBuffers.size(); idx++) {
460 if (!mBuffers[idx].inUse) {
461 if (mBuffers[idx].handle != nullptr) {
462 // Found an available record, so stop looking
463 break;
464 }
465 }
466 }
467 if (idx >= mBuffers.size()) {
468 // This shouldn't happen since we already checked mFramesInUse vs mFramesAllowed
469 ALOGE("Failed to find an available buffer slot\n");
470 } else {
471 // We're going to make the frame busy
472 mBuffers[idx].inUse = true;
473 mFramesInUse++;
474 timeForFrame = true;
475 }
476 }
477 }
478
479 if (timeForFrame) {
480 // Assemble the buffer description we'll transmit below
481 BufferDesc_1_1 newBuffer = {};
482 AHardwareBuffer_Desc* pDesc =
483 reinterpret_cast<AHardwareBuffer_Desc *>(&newBuffer.buffer.description);
484 pDesc->width = mWidth;
485 pDesc->height = mHeight;
486 pDesc->layers = 1;
487 pDesc->format = mFormat;
488 pDesc->usage = mUsage;
489 pDesc->stride = mStride;
490 newBuffer.buffer.nativeHandle = mBuffers[idx].handle;
491 newBuffer.pixelSize = sizeof(uint32_t);
492 newBuffer.bufferId = idx;
493
494 // Write test data into the image buffer
495 fillTestFrame(newBuffer);
496
497 // Issue the (asynchronous) callback to the client -- can't be holding the lock
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700498 auto result = mStream->deliverFrame_1_1(newBuffer);
Changyeon Jo2400b692019-07-18 21:32:48 -0700499 if (result.isOk()) {
500 ALOGD("Delivered %p as id %d",
501 newBuffer.buffer.nativeHandle.getNativeHandle(), newBuffer.bufferId);
502 } else {
503 // This can happen if the client dies and is likely unrecoverable.
504 // To avoid consuming resources generating failing calls, we stop sending
505 // frames. Note, however, that the stream remains in the "STREAMING" state
506 // until cleaned up on the main thread.
507 ALOGE("Frame delivery call failed in the transport layer.");
508
509 // Since we didn't actually deliver it, mark the frame as available
510 std::lock_guard<std::mutex> lock(mAccessLock);
511 mBuffers[idx].inUse = false;
512 mFramesInUse--;
513
514 break;
515 }
516 }
517
518 // We arbitrarily choose to generate frames at 12 fps to ensure we pass the 10fps test requirement
519 static const int kTargetFrameRate = 12;
520 static const nsecs_t kTargetFrameTimeUs = 1000*1000 / kTargetFrameRate;
521 const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
522 const nsecs_t workTimeUs = (now - startTime) / 1000;
523 const nsecs_t sleepDurationUs = kTargetFrameTimeUs - workTimeUs;
524 if (sleepDurationUs > 0) {
525 usleep(sleepDurationUs);
526 }
527 }
528
529 // If we've been asked to stop, send an event to signal the actual end of stream
530 EvsEvent event;
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700531 event.aType = EvsEventType::STREAM_STOPPED;
532 auto result = mStream->notify(event);
Changyeon Jo2400b692019-07-18 21:32:48 -0700533 if (!result.isOk()) {
534 ALOGE("Error delivering end of stream marker");
535 }
536
537 return;
538}
539
540
541void EvsCamera::fillTestFrame(const BufferDesc_1_1& buff) {
542 // Lock our output buffer for writing
543 uint32_t *pixels = nullptr;
544 const AHardwareBuffer_Desc* pDesc =
545 reinterpret_cast<const AHardwareBuffer_Desc *>(&buff.buffer.description);
546 GraphicBufferMapper &mapper = GraphicBufferMapper::get();
547 mapper.lock(buff.buffer.nativeHandle,
548 GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_NEVER,
549 android::Rect(pDesc->width, pDesc->height),
550 (void **) &pixels);
551
552 // If we failed to lock the pixel buffer, we're about to crash, but log it first
553 if (!pixels) {
554 ALOGE("Camera failed to gain access to image buffer for writing");
555 }
556
557 // Fill in the test pixels
558 for (unsigned row = 0; row < pDesc->height; row++) {
559 for (unsigned col = 0; col < pDesc->width; col++) {
560 // Index into the row to check the pixel at this column.
561 // We expect 0xFF in the LSB channel, a vertical gradient in the
562 // second channel, a horitzontal gradient in the third channel, and
563 // 0xFF in the MSB.
564 // The exception is the very first 32 bits which is used for the
565 // time varying frame signature to avoid getting fooled by a static image.
566 uint32_t expectedPixel = 0xFF0000FF | // MSB and LSB
567 ((row & 0xFF) << 8) | // vertical gradient
568 ((col & 0xFF) << 16); // horizontal gradient
569 if ((row | col) == 0) {
570 static uint32_t sFrameTicker = 0;
571 expectedPixel = (sFrameTicker) & 0xFF;
572 sFrameTicker++;
573 }
574 pixels[col] = expectedPixel;
575 }
576 // Point to the next row
577 // NOTE: stride retrieved from gralloc is in units of pixels
578 pixels = pixels + pDesc->stride;
579 }
580
581 // Release our output buffer
582 mapper.unlock(buff.buffer.nativeHandle);
583}
584
585
586void EvsCamera::fillTestFrame(const BufferDesc_1_0& buff) {
587 BufferDesc_1_1 newBufDesc = {};
588 AHardwareBuffer_Desc desc = {
589 buff.width, // width
590 buff.height, // height
591 1, // layers, always 1 for EVS
592 buff.format, // One of AHardwareBuffer_Format
593 buff.usage, // Combination of AHardwareBuffer_UsageFlags
594 buff.stride, // Row stride in pixels
595 0, // Reserved
596 0 // Reserved
597 };
598 memcpy(&desc, &newBufDesc.buffer.description, sizeof(desc));
599 newBufDesc.buffer.nativeHandle = buff.memHandle;
600 newBufDesc.pixelSize = buff.pixelSize;
601 newBufDesc.bufferId = buff.bufferId;
602
603 return fillTestFrame(newBufDesc);
604}
605
606
607void EvsCamera::returnBuffer(const uint32_t bufferId, const buffer_handle_t memHandle) {
608 std::lock_guard <std::mutex> lock(mAccessLock);
609
610 if (memHandle == nullptr) {
611 ALOGE("ignoring doneWithFrame called with null handle");
612 } else if (bufferId >= mBuffers.size()) {
613 ALOGE("ignoring doneWithFrame called with invalid bufferId %d (max is %zu)",
614 bufferId, mBuffers.size()-1);
615 } else if (!mBuffers[bufferId].inUse) {
616 ALOGE("ignoring doneWithFrame called on frame %d which is already free",
617 bufferId);
618 } else {
619 // Mark the frame as available
620 mBuffers[bufferId].inUse = false;
621 mFramesInUse--;
622
623 // If this frame's index is high in the array, try to move it down
624 // to improve locality after mFramesAllowed has been reduced.
625 if (bufferId >= mFramesAllowed) {
626 // Find an empty slot lower in the array (which should always exist in this case)
627 for (auto&& rec : mBuffers) {
628 if (rec.handle == nullptr) {
629 rec.handle = mBuffers[bufferId].handle;
630 mBuffers[bufferId].handle = nullptr;
631 break;
632 }
633 }
634 }
635 }
636}
637
638
Changyeon Joc6fa0ab2019-10-12 05:25:44 -0700639sp<EvsCamera> EvsCamera::Create(const char *deviceName) {
640 unique_ptr<ConfigManager::CameraInfo> nullCamInfo = nullptr;
641
642 return Create(deviceName, nullCamInfo);
643}
644
645
646sp<EvsCamera> EvsCamera::Create(const char *deviceName,
647 unique_ptr<ConfigManager::CameraInfo> &camInfo,
648 const Stream *streamCfg) {
649 sp<EvsCamera> evsCamera = new EvsCamera(deviceName, camInfo);
650 if (evsCamera == nullptr) {
651 return nullptr;
652 }
653
654 /* default implementation does not use a given configuration */
655 (void)streamCfg;
656
657 /* Use the first resolution from the list for the testing */
658 auto it = camInfo->streamConfigurations.begin();
659 evsCamera->mWidth = it->second[1];
660 evsCamera->mHeight = it->second[2];
661 evsCamera->mDescription.v1.vendorFlags = 0xFFFFFFFF; // Arbitrary test value
662
663 evsCamera->mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
664 evsCamera->mUsage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE |
665 GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_RARELY;
666
667 return evsCamera;
668}
669
670
Changyeon Jo2400b692019-07-18 21:32:48 -0700671} // namespace implementation
672} // namespace V1_0
673} // namespace evs
674} // namespace automotive
675} // namespace hardware
676} // namespace android