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