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