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 "VirtualCamera.h"
18 
19 #include "Enumerator.h"
20 #include "HalCamera.h"
21 
22 #include <android-base/file.h>
23 #include <android-base/logging.h>
24 #include <android-base/stringprintf.h>
25 #include <android/hardware_buffer.h>
26 
27 #include <assert.h>
28 
29 using ::android::base::StringAppendF;
30 using ::android::base::StringPrintf;
31 using ::android::base::WriteStringToFd;
32 using ::android::hardware::hidl_handle;
33 using ::android::hardware::hidl_string;
34 using ::android::hardware::hidl_vec;
35 using ::android::hardware::Return;
36 using ::android::hardware::Void;
37 using ::android::hardware::automotive::evs::V1_0::DisplayState;
38 using ::android::hardware::automotive::evs::V1_0::EvsResult;
39 using ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
40 using ::android::hardware::automotive::evs::V1_1::EvsEventDesc;
41 using ::android::hardware::automotive::evs::V1_1::EvsEventType;
42 
43 using BufferDesc_1_0 = ::android::hardware::automotive::evs::V1_0::BufferDesc;
44 using BufferDesc_1_1 = ::android::hardware::automotive::evs::V1_1::BufferDesc;
45 using IEvsCamera_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCamera;
46 using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera;
47 using IEvsCameraStream_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCameraStream;
48 using IEvsCameraStream_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCameraStream;
49 using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
50 using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
51 
52 namespace android::automotive::evs::V1_1::implementation {
53 
VirtualCamera(const std::vector<sp<HalCamera>> & halCameras)54 VirtualCamera::VirtualCamera(const std::vector<sp<HalCamera>>& halCameras) : mStreamState(STOPPED) {
55     for (auto&& cam : halCameras) {
56         mHalCamera.try_emplace(cam->getId(), cam);
57     }
58 }
59 
~VirtualCamera()60 VirtualCamera::~VirtualCamera() {
61     shutdown();
62 }
63 
shutdown()64 void VirtualCamera::shutdown() {
65     // In normal operation, the stream should already be stopped by the time we get here
66     if (mStreamState == RUNNING) {
67         // Note that if we hit this case, no terminating frame will be sent to the client,
68         // but they're probably already dead anyway.
69         LOG(WARNING) << "Virtual camera being shutdown while stream is running";
70 
71         // Tell the frame delivery pipeline we don't want any more frames
72         {
73             std::unique_lock<std::mutex> lock(mFrameDeliveryMutex);
74             mStreamState = STOPPING;
75         }
76 
77         // Awakes the capture thread; this thread will terminate.
78         mFramesReadySignal.notify_all();
79 
80         // Join a capture thread
81         if (mCaptureThread.joinable()) {
82             mCaptureThread.join();
83         }
84 
85         std::lock_guard<std::recursive_mutex> lock(mFramesHeldMutex);
86 
87         // Returns buffers held by this client
88         for (auto&& [key, hwCamera] : mHalCamera) {
89             auto pHwCamera = hwCamera.promote();
90             if (pHwCamera == nullptr) {
91                 LOG(WARNING) << "Camera device " << key << " is not alive.";
92                 continue;
93             }
94 
95             if (mFramesHeld[key].size() > 0) {
96                 LOG(WARNING) << "VirtualCamera destructing with frames in flight.";
97 
98                 // Return to the underlying hardware camera any buffers the client was holding
99                 for (auto&& heldBuffer : mFramesHeld[key]) {
100                     // Tell our parent that we're done with this buffer
101                     pHwCamera->doneWithFrame(heldBuffer);
102                 }
103                 mFramesHeld[key].clear();
104             }
105 
106             // Retire from a primary client
107             pHwCamera->unsetMaster(this);
108 
109             // Give the underlying hardware camera the heads up that it might be time to stop
110             pHwCamera->clientStreamEnding(this);
111 
112             // Retire from the participating HW camera's client list
113             pHwCamera->disownVirtualCamera(this);
114         }
115 
116         mFramesHeld.clear();
117 
118         // Drop our reference to our associated hardware camera
119         mHalCamera.clear();
120     }
121 }
122 
getHalCameras()123 std::vector<sp<HalCamera>> VirtualCamera::getHalCameras() {
124     std::vector<sp<HalCamera>> cameras;
125     for (auto&& [key, cam] : mHalCamera) {
126         auto ptr = cam.promote();
127         if (ptr != nullptr) {
128             cameras.emplace_back(ptr);
129         }
130     }
131 
132     return cameras;
133 }
134 
deliverFrame(const BufferDesc_1_1 & bufDesc)135 bool VirtualCamera::deliverFrame(const BufferDesc_1_1& bufDesc) {
136     if (mStreamState == STOPPED) {
137         // A stopped stream gets no frames
138         LOG(ERROR) << "A stopped stream should not get any frames";
139         return false;
140     }
141 
142     bool dropFrame;
143     int framesHeld;
144     // Part of dropframe logic here to limit the scope of the mutex lock
145     {
146         std::lock_guard<std::recursive_mutex> lock(mFramesHeldMutex);
147         framesHeld = mFramesHeld[bufDesc.deviceId].size();
148         dropFrame = framesHeld >= mFramesAllowed;
149         if (!dropFrame) {
150             // Keep a record of this frame so we can clean up if we have to in case of client death
151             mFramesHeld[bufDesc.deviceId].emplace_back(bufDesc);
152         }
153     }
154     if (dropFrame) {
155         // Indicate that we declined to send the frame to the client because they're at quota
156         LOG(INFO) << "Skipping new frame as we hold " << framesHeld << " of " << mFramesAllowed;
157 
158         if (mStream_1_1 != nullptr) {
159             // Report a frame drop to v1.1 client.
160             EvsEventDesc event;
161             event.deviceId = bufDesc.deviceId;
162             event.aType = EvsEventType::FRAME_DROPPED;
163             auto result = mStream_1_1->notify(event);
164             if (!result.isOk()) {
165                 LOG(ERROR) << "Error delivering end of stream event";
166             }
167         }
168 
169         // Marks that a new frame has arrived though it was not accepted
170         {
171             std::lock_guard<std::mutex> lock(mFrameDeliveryMutex);
172             mSourceCameras.erase(bufDesc.deviceId);
173             mFramesReadySignal.notify_all();
174         }
175 
176         return false;
177     } else {
178         // v1.0 client uses an old frame-delivery mechanism.
179         if (mStream_1_1 == nullptr) {
180             // Forward a frame to v1.0 client
181             BufferDesc_1_0 frame_1_0 = {};
182             const AHardwareBuffer_Desc* pDesc =
183                     reinterpret_cast<const AHardwareBuffer_Desc*>(&bufDesc.buffer.description);
184             frame_1_0.width = pDesc->width;
185             frame_1_0.height = pDesc->height;
186             frame_1_0.format = pDesc->format;
187             frame_1_0.usage = pDesc->usage;
188             frame_1_0.stride = pDesc->stride;
189             frame_1_0.memHandle = bufDesc.buffer.nativeHandle;
190             frame_1_0.pixelSize = bufDesc.pixelSize;
191             frame_1_0.bufferId = bufDesc.bufferId;
192 
193             mStream->deliverFrame(frame_1_0);
194         } else if (mCaptureThread.joinable()) {
195             // Keep forwarding frames as long as a capture thread is alive
196             // Notify a new frame receipt
197             {
198                 std::lock_guard<std::mutex> lock(mFrameDeliveryMutex);
199                 mSourceCameras.erase(bufDesc.deviceId);
200             }
201             mFramesReadySignal.notify_all();
202         }
203 
204         return true;
205     }
206 }
207 
notify(const EvsEventDesc & event)208 bool VirtualCamera::notify(const EvsEventDesc& event) {
209     switch (event.aType) {
210         case EvsEventType::STREAM_STOPPED:
211             if (mStreamState != STOPPING) {
212                 // Warn if we got an unexpected stream termination
213                 LOG(WARNING) << "Stream unexpectedly stopped, current status " << mStreamState;
214 
215                 // Clean up the resource and forward an event to the client
216                 stopVideoStream();
217 
218                 // This event is handled properly.
219                 return true;
220             }
221 
222             if (mStream_1_1 == nullptr) {
223                 // Send a null frame instead, for v1.0 client
224                 auto result = mStream->deliverFrame({});
225                 if (!result.isOk()) {
226                     LOG(ERROR) << "Error delivering end of stream marker";
227                 }
228             }
229             break;
230 
231         // v1.0 client will ignore all other events.
232         case EvsEventType::PARAMETER_CHANGED:
233             LOG(DEBUG) << "A camera parameter " << event.payload[0] << " is set to "
234                        << event.payload[1];
235             break;
236 
237         case EvsEventType::MASTER_RELEASED:
238             LOG(DEBUG) << "The primary client has been released";
239             break;
240 
241         default:
242             LOG(WARNING) << "Unknown event id " << static_cast<int32_t>(event.aType);
243             break;
244     }
245 
246     if (mStream_1_1 != nullptr) {
247         // Forward a received event to the v1.1 client
248         auto result = mStream_1_1->notify(event);
249         if (!result.isOk()) {
250             LOG(ERROR) << "Failed to forward an event";
251             return false;
252         }
253     }
254 
255     return true;
256 }
257 
258 // Methods from ::android::hardware::automotive::evs::V1_0::IEvsCamera follow.
getCameraInfo(getCameraInfo_cb info_cb)259 Return<void> VirtualCamera::getCameraInfo(getCameraInfo_cb info_cb) {
260     // Straight pass through to hardware layer
261     if (mHalCamera.size() > 1) {
262         LOG(ERROR) << __FUNCTION__ << " must NOT be called on a logical camera object.";
263         info_cb({});
264         return Void();
265     }
266 
267     auto halCamera = mHalCamera.begin()->second.promote();
268     if (halCamera != nullptr) {
269         return halCamera->getHwCamera()->getCameraInfo(info_cb);
270     } else {
271         info_cb({});
272         return Void();
273     }
274 }
275 
setMaxFramesInFlight(uint32_t bufferCount)276 Return<EvsResult> VirtualCamera::setMaxFramesInFlight(uint32_t bufferCount) {
277     // How many buffers are we trying to add (or remove if negative)
278     int bufferCountChange = bufferCount - mFramesAllowed;
279 
280     // Ask our parent for more buffers
281     bool result = true;
282     std::vector<sp<HalCamera>> changedCameras;
283     for (auto&& [key, hwCamera] : mHalCamera) {
284         auto pHwCam = hwCamera.promote();
285         if (pHwCam == nullptr) {
286             continue;
287         }
288 
289         result = pHwCam->changeFramesInFlight(bufferCountChange);
290         if (!result) {
291             LOG(ERROR) << key << ": Failed to change buffer count by " << bufferCountChange
292                        << " to " << bufferCount;
293             break;
294         }
295 
296         changedCameras.emplace_back(pHwCam);
297     }
298 
299     // Update our notion of how many frames we're allowed
300     mFramesAllowed = bufferCount;
301 
302     if (!result) {
303         // Rollback changes because we failed to update all cameras
304         for (auto&& hwCamera : changedCameras) {
305             LOG(WARNING) << "Rollback a change on  " << hwCamera->getId();
306             hwCamera->changeFramesInFlight(-bufferCountChange);
307         }
308 
309         // Restore the original buffer count
310         mFramesAllowed -= bufferCountChange;
311         return EvsResult::BUFFER_NOT_AVAILABLE;
312     } else {
313         return EvsResult::OK;
314     }
315 }
316 
startVideoStream(const::android::sp<IEvsCameraStream_1_0> & stream)317 Return<EvsResult> VirtualCamera::startVideoStream(
318         const ::android::sp<IEvsCameraStream_1_0>& stream) {
319     // We only support a single stream at a time
320     if (mStreamState != STOPPED) {
321         LOG(ERROR) << "Ignoring startVideoStream call when a stream is already running.";
322         return EvsResult::STREAM_ALREADY_RUNNING;
323     }
324 
325     // Validate our held frame count is starting out at zero as we expect
326     {
327         std::lock_guard<std::recursive_mutex> lock(mFramesHeldMutex);
328         assert(mFramesHeld.size() == 0);
329     }
330 
331     // Record the user's callback for use when we have a frame ready
332     mStream = stream;
333     mStream_1_1 = IEvsCameraStream_1_1::castFrom(stream).withDefault(nullptr);
334     if (mStream_1_1 == nullptr) {
335         LOG(INFO) << "Start video stream for v1.0 client.";
336     } else {
337         LOG(INFO) << "Start video stream for v1.1 client.";
338     }
339 
340     mStreamState = RUNNING;
341 
342     // Tell the underlying camera hardware that we want to stream
343     bool cleanUpAndReturn = true;
344     auto iter = mHalCamera.begin();
345     while (iter != mHalCamera.end()) {
346         auto pHwCamera = iter->second.promote();
347         if (pHwCamera == nullptr) {
348             LOG(WARNING) << "Failed to start a video stream on " << iter->first;
349             ++iter;
350             continue;
351         }
352 
353         LOG(INFO) << __FUNCTION__ << " starts a video stream on " << iter->first;
354         Return<EvsResult> result = pHwCamera->clientStreamStarting();
355         if ((!result.isOk()) || (result != EvsResult::OK)) {
356             LOG(ERROR) << "Failed to start a video stream on " << iter->first;
357             cleanUpAndReturn = true;
358             break;
359         }
360 
361         cleanUpAndReturn = false;
362         ++iter;
363     }
364 
365     if (cleanUpAndReturn) {
366         // If we failed to start the underlying stream, then we're not actually running
367         mStream = mStream_1_1 = nullptr;
368         mStreamState = STOPPED;
369 
370         // Request to stop streams started by this client.
371         auto rb = mHalCamera.begin();
372         while (rb != iter) {
373             auto ptr = rb->second.promote();
374             if (ptr != nullptr) {
375                 ptr->clientStreamEnding(this);
376             }
377             ++rb;
378         }
379         return EvsResult::UNDERLYING_SERVICE_ERROR;
380     }
381 
382     // Start a thread that waits on the fence and forwards collected frames
383     // to the v1.1 client.
384     auto pHwCamera = mHalCamera.begin()->second.promote();
385     if (mStream_1_1 != nullptr && pHwCamera != nullptr) {
386         mCaptureThread = std::thread([this]() {
387             // TODO(b/145466570): With a proper camera hang handler, we may want
388             // to reduce an amount of timeout.
389             constexpr auto kFrameTimeout = 5s;  // timeout in seconds.
390             int64_t lastFrameTimestamp = -1;
391             while (mStreamState == RUNNING) {
392                 unsigned count = 0;
393                 for (auto&& [key, hwCamera] : mHalCamera) {
394                     auto pHwCamera = hwCamera.promote();
395                     if (pHwCamera == nullptr) {
396                         LOG(WARNING) << "Invalid camera " << key << " is ignored.";
397                         continue;
398                     }
399 
400                     pHwCamera->requestNewFrame(this, lastFrameTimestamp);
401                     {
402                         std::lock_guard<std::mutex> lock(mFrameDeliveryMutex);
403                         mSourceCameras.emplace(pHwCamera->getId());
404                     }
405                     ++count;
406                 }
407 
408                 std::unique_lock<std::mutex> lock(mFrameDeliveryMutex);
409                 if (!mFramesReadySignal.wait_for(lock, kFrameTimeout,
410                                                  [this]() REQUIRES(mFrameDeliveryMutex) {
411                                                      // Stops waiting if
412                                                      // 1) we've requested to stop capturing
413                                                      //    new frames
414                                                      // 2) or, we've got all frames
415                                                      return mStreamState != RUNNING ||
416                                                              mSourceCameras.empty();
417                                                  })) {
418                     // This happens when either a new frame does not arrive
419                     // before a timer expires or we're requested to stop
420                     // capturing frames.
421                     break;
422                 } else if (mStreamState == RUNNING) {
423                     // Fetch frames and forward to the client
424                     std::lock_guard<std::recursive_mutex> lock(mFramesHeldMutex);
425                     if (mFramesHeld.size() > 0 && mStream_1_1 != nullptr) {
426                         // Pass this buffer through to our client
427                         hardware::hidl_vec<BufferDesc_1_1> frames;
428                         frames.resize(count);
429                         unsigned i = 0;
430                         for (auto&& [key, hwCamera] : mHalCamera) {
431                             auto pHwCamera = hwCamera.promote();
432                             if (pHwCamera == nullptr) {
433                                 continue;
434                             }
435                             if (mFramesHeld[key].size() == 0) {
436                                 continue;
437                             }
438 
439                             const auto frame = mFramesHeld[key].back();
440                             if (frame.timestamp > lastFrameTimestamp) {
441                                 lastFrameTimestamp = frame.timestamp;
442                             }
443                             frames[i++] = frame;
444                         }
445 
446                         auto ret = mStream_1_1->deliverFrame_1_1(frames);
447                         if (!ret.isOk()) {
448                             LOG(WARNING) << "Failed to forward frames";
449                         }
450                     }
451                 } else if (mStreamState != RUNNING) {
452                     LOG(DEBUG) << "Requested to stop capturing frames";
453                 }
454             }
455 
456             LOG(DEBUG) << "Exiting a capture thread";
457         });
458     }
459 
460     // TODO(changyeon):
461     // Detect and exit if we encounter a stalled stream or unresponsive driver?
462     // Consider using a timer and watching for frame arrival?
463 
464     return EvsResult::OK;
465 }
466 
doneWithFrame(const BufferDesc_1_0 & buffer)467 Return<void> VirtualCamera::doneWithFrame(const BufferDesc_1_0& buffer) {
468     std::lock_guard<std::recursive_mutex> lock(mFramesHeldMutex);
469 
470     if (buffer.memHandle == nullptr) {
471         LOG(ERROR) << "Ignoring doneWithFrame called with invalid handle";
472     } else if (mFramesHeld.size() > 1) {
473         LOG(ERROR) << __FUNCTION__ << " must NOT be called on a logical camera object.";
474     } else {
475         // Find this buffer in our "held" list
476         auto& frameQueue = mFramesHeld.begin()->second;
477         auto it = frameQueue.begin();
478         while (it != frameQueue.end()) {
479             if (it->bufferId == buffer.bufferId) {
480                 // found it!
481                 break;
482             }
483             ++it;
484         }
485         if (it == frameQueue.end()) {
486             // We should always find the frame in our "held" list
487             LOG(ERROR) << "Ignoring doneWithFrame called with unrecognized frameID "
488                        << buffer.bufferId;
489         } else {
490             // Take this frame out of our "held" list
491             frameQueue.erase(it);
492 
493             // Tell our parent that we're done with this buffer
494             auto pHwCamera = mHalCamera.begin()->second.promote();
495             if (pHwCamera != nullptr) {
496                 pHwCamera->doneWithFrame(buffer);
497             } else {
498                 LOG(WARNING) << "Possible memory leak because a device "
499                              << mHalCamera.begin()->first << " is not valid.";
500             }
501         }
502     }
503 
504     return Void();
505 }
506 
stopVideoStream()507 Return<void> VirtualCamera::stopVideoStream() {
508     if (mStreamState == RUNNING) {
509         // Tell the frame delivery pipeline we don't want any more frames
510         mStreamState = STOPPING;
511 
512         // Awake the capture thread; this thread will terminate.
513         mFramesReadySignal.notify_all();
514 
515         // Deliver the stream-ending notification
516         if (mStream_1_1 != nullptr) {
517             // v1.1 client waits for a stream stopped event
518             EvsEventDesc event;
519             event.aType = EvsEventType::STREAM_STOPPED;
520             auto result = mStream_1_1->notify(event);
521             if (!result.isOk()) {
522                 LOG(ERROR) << "Error delivering end of stream event";
523             }
524         } else {
525             // v1.0 client expects a null frame at the end of the stream
526             auto result = mStream->deliverFrame({});
527             if (!result.isOk()) {
528                 LOG(ERROR) << "Error delivering end of stream marker";
529             }
530         }
531 
532         // Since we are single threaded, no frame can be delivered while this function is running,
533         // so we can go directly to the STOPPED state here on the server.
534         // Note, however, that there still might be frames already queued that client will see
535         // after returning from the client side of this call.
536         mStreamState = STOPPED;
537 
538         // Give the underlying hardware camera the heads up that it might be time to stop
539         for (auto&& [key, hwCamera] : mHalCamera) {
540             auto pHwCamera = hwCamera.promote();
541             if (pHwCamera != nullptr) {
542                 pHwCamera->clientStreamEnding(this);
543             }
544         }
545 
546         // Signal a condition to unblock a capture thread and then join
547         {
548             std::lock_guard<std::mutex> lock(mFrameDeliveryMutex);
549             mSourceCameras.clear();
550             mFramesReadySignal.notify_all();
551         }
552 
553         if (mCaptureThread.joinable()) {
554             mCaptureThread.join();
555         }
556     }
557 
558     return Void();
559 }
560 
getExtendedInfo(uint32_t opaqueIdentifier)561 Return<int32_t> VirtualCamera::getExtendedInfo(uint32_t opaqueIdentifier) {
562     if (mHalCamera.size() > 1) {
563         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
564         return 0;
565     }
566 
567     // Pass straight through to the hardware device
568     auto pHwCamera = mHalCamera.begin()->second.promote();
569     if (pHwCamera != nullptr) {
570         return pHwCamera->getHwCamera()->getExtendedInfo(opaqueIdentifier);
571     } else {
572         LOG(WARNING) << mHalCamera.begin()->first << " is invalid.";
573         return 0;
574     }
575 }
576 
setExtendedInfo(uint32_t opaqueIdentifier,int32_t opaqueValue)577 Return<EvsResult> VirtualCamera::setExtendedInfo(uint32_t opaqueIdentifier, int32_t opaqueValue) {
578     if (mHalCamera.size() > 1) {
579         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
580         return EvsResult::INVALID_ARG;
581     }
582 
583     // Pass straight through to the hardware device
584     auto pHwCamera = mHalCamera.begin()->second.promote();
585     if (pHwCamera != nullptr) {
586         return pHwCamera->getHwCamera()->setExtendedInfo(opaqueIdentifier, opaqueValue);
587     } else {
588         LOG(WARNING) << mHalCamera.begin()->first << " is invalid.";
589         return EvsResult::INVALID_ARG;
590     }
591 }
592 
593 // Methods from ::android::hardware::automotive::evs::V1_1::IEvsCamera follow.
getCameraInfo_1_1(getCameraInfo_1_1_cb info_cb)594 Return<void> VirtualCamera::getCameraInfo_1_1(getCameraInfo_1_1_cb info_cb) {
595     if (mHalCamera.size() > 1) {
596         // Logical camera description is stored in VirtualCamera object.
597         info_cb(*mDesc);
598         return Void();
599     }
600 
601     // Straight pass through to hardware layer
602     auto pHwCamera = mHalCamera.begin()->second.promote();
603     if (pHwCamera == nullptr) {
604         // Return an empty list
605         info_cb({});
606         return Void();
607     }
608 
609     auto hwCamera_1_1 = IEvsCamera_1_1::castFrom(pHwCamera->getHwCamera()).withDefault(nullptr);
610     if (hwCamera_1_1 != nullptr) {
611         return hwCamera_1_1->getCameraInfo_1_1(info_cb);
612     } else {
613         // Return an empty list
614         info_cb({});
615         return Void();
616     }
617 }
618 
getPhysicalCameraInfo(const hidl_string & deviceId,getPhysicalCameraInfo_cb info_cb)619 Return<void> VirtualCamera::getPhysicalCameraInfo(const hidl_string& deviceId,
620                                                   getPhysicalCameraInfo_cb info_cb) {
621     auto device = mHalCamera.find(deviceId);
622     if (device != mHalCamera.end()) {
623         // Straight pass through to hardware layer
624         auto pHwCamera = device->second.promote();
625         if (pHwCamera != nullptr) {
626             auto hwCamera_1_1 =
627                     IEvsCamera_1_1::castFrom(pHwCamera->getHwCamera()).withDefault(nullptr);
628             if (hwCamera_1_1 != nullptr) {
629                 return hwCamera_1_1->getCameraInfo_1_1(info_cb);
630             } else {
631                 LOG(WARNING) << "Failed to promote HW camera to v1.1.";
632             }
633         } else {
634             LOG(WARNING) << "Camera device " << deviceId << " is not alive.";
635         }
636     } else {
637         LOG(WARNING) << " Requested device " << deviceId << " does not back this device.";
638     }
639 
640     // Return an empty list
641     info_cb({});
642     return Void();
643 }
644 
doneWithFrame_1_1(const hardware::hidl_vec<BufferDesc_1_1> & buffers)645 Return<EvsResult> VirtualCamera::doneWithFrame_1_1(
646         const hardware::hidl_vec<BufferDesc_1_1>& buffers) {
647     std::lock_guard<std::recursive_mutex> lock(mFramesHeldMutex);
648     for (auto&& buffer : buffers) {
649         if (buffer.buffer.nativeHandle == nullptr) {
650             LOG(WARNING) << "Ignoring doneWithFrame called with invalid handle";
651         } else {
652             // Find this buffer in our "held" list
653             auto it = mFramesHeld[buffer.deviceId].begin();
654             while (it != mFramesHeld[buffer.deviceId].end()) {
655                 if (it->bufferId == buffer.bufferId) {
656                     // found it!
657                     break;
658                 }
659                 ++it;
660             }
661             if (it == mFramesHeld[buffer.deviceId].end()) {
662                 // We should always find the frame in our "held" list
663                 LOG(ERROR) << "Ignoring doneWithFrame called with unrecognized frameID "
664                            << buffer.bufferId;
665             } else {
666                 // Take this frame out of our "held" list
667                 mFramesHeld[buffer.deviceId].erase(it);
668 
669                 // Tell our parent that we're done with this buffer
670                 auto pHwCamera = mHalCamera[buffer.deviceId].promote();
671                 if (pHwCamera != nullptr) {
672                     pHwCamera->doneWithFrame(buffer);
673                 } else {
674                     LOG(WARNING) << "Possible memory leak; " << buffer.deviceId << " is not valid.";
675                 }
676             }
677         }
678     }
679 
680     return EvsResult::OK;
681 }
682 
setMaster()683 Return<EvsResult> VirtualCamera::setMaster() {
684     if (mHalCamera.size() > 1) {
685         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
686         return EvsResult::INVALID_ARG;
687     }
688 
689     auto pHwCamera = mHalCamera.begin()->second.promote();
690     if (pHwCamera != nullptr) {
691         return pHwCamera->setMaster(this);
692     } else {
693         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
694         return EvsResult::INVALID_ARG;
695     }
696 }
697 
forceMaster(const sp<IEvsDisplay_1_0> & display)698 Return<EvsResult> VirtualCamera::forceMaster(const sp<IEvsDisplay_1_0>& display) {
699     if (mHalCamera.size() > 1) {
700         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
701         return EvsResult::INVALID_ARG;
702     }
703 
704     if (display == nullptr) {
705         LOG(ERROR) << __FUNCTION__ << ": Passed display is invalid";
706         return EvsResult::INVALID_ARG;
707     }
708 
709     DisplayState state = display->getDisplayState();
710     if (state == DisplayState::NOT_OPEN || state == DisplayState::DEAD ||
711         state >= DisplayState::NUM_STATES) {
712         LOG(ERROR) << __FUNCTION__ << ": Passed display is in invalid state";
713         return EvsResult::INVALID_ARG;
714     }
715 
716     auto pHwCamera = mHalCamera.begin()->second.promote();
717     if (pHwCamera != nullptr) {
718         return pHwCamera->forceMaster(this);
719     } else {
720         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
721         return EvsResult::INVALID_ARG;
722     }
723 }
724 
unsetMaster()725 Return<EvsResult> VirtualCamera::unsetMaster() {
726     if (mHalCamera.size() > 1) {
727         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
728         return EvsResult::INVALID_ARG;
729     }
730 
731     auto pHwCamera = mHalCamera.begin()->second.promote();
732     if (pHwCamera != nullptr) {
733         return pHwCamera->unsetMaster(this);
734     } else {
735         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
736         return EvsResult::INVALID_ARG;
737     }
738 }
739 
getParameterList(getParameterList_cb _hidl_cb)740 Return<void> VirtualCamera::getParameterList(getParameterList_cb _hidl_cb) {
741     if (mHalCamera.size() > 1) {
742         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
743 
744         // Return an empty list
745         _hidl_cb({});
746         return Void();
747     }
748 
749     // Straight pass through to hardware layer
750     auto pHwCamera = mHalCamera.begin()->second.promote();
751     if (pHwCamera == nullptr) {
752         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
753 
754         // Return an empty list
755         _hidl_cb({});
756         return Void();
757     }
758 
759     auto hwCamera_1_1 = IEvsCamera_1_1::castFrom(pHwCamera->getHwCamera()).withDefault(nullptr);
760     if (hwCamera_1_1 != nullptr) {
761         return hwCamera_1_1->getParameterList(_hidl_cb);
762     } else {
763         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first
764                      << " does not support a parameter programming.";
765 
766         // Return an empty list
767         _hidl_cb({});
768         return Void();
769     }
770 }
771 
getIntParameterRange(CameraParam id,getIntParameterRange_cb _hidl_cb)772 Return<void> VirtualCamera::getIntParameterRange(CameraParam id, getIntParameterRange_cb _hidl_cb) {
773     if (mHalCamera.size() > 1) {
774         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
775 
776         // Return [0, 0, 0]
777         _hidl_cb(0, 0, 0);
778         return Void();
779     }
780 
781     // Straight pass through to hardware layer
782     auto pHwCamera = mHalCamera.begin()->second.promote();
783     if (pHwCamera == nullptr) {
784         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
785 
786         // Return [0, 0, 0]
787         _hidl_cb(0, 0, 0);
788         return Void();
789     }
790 
791     auto hwCamera_1_1 = IEvsCamera_1_1::castFrom(pHwCamera->getHwCamera()).withDefault(nullptr);
792     if (hwCamera_1_1 != nullptr) {
793         return hwCamera_1_1->getIntParameterRange(id, _hidl_cb);
794     } else {
795         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first
796                      << " does not support a parameter programming.";
797 
798         // Return [0, 0, 0]
799         _hidl_cb(0, 0, 0);
800         return Void();
801     }
802     return Void();
803 }
804 
setIntParameter(CameraParam id,int32_t value,setIntParameter_cb _hidl_cb)805 Return<void> VirtualCamera::setIntParameter(CameraParam id, int32_t value,
806                                             setIntParameter_cb _hidl_cb) {
807     hardware::hidl_vec<int32_t> values;
808     EvsResult status = EvsResult::INVALID_ARG;
809     if (mHalCamera.size() > 1) {
810         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
811         _hidl_cb(status, values);
812         return Void();
813     }
814 
815     auto pHwCamera = mHalCamera.begin()->second.promote();
816     if (pHwCamera == nullptr) {
817         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
818         _hidl_cb(status, values);
819         return Void();
820     }
821 
822     status = pHwCamera->setParameter(this, id, &value);
823 
824     values.resize(1);
825     values[0] = value;
826     _hidl_cb(status, values);
827 
828     return Void();
829 }
830 
getIntParameter(CameraParam id,getIntParameter_cb _hidl_cb)831 Return<void> VirtualCamera::getIntParameter(CameraParam id, getIntParameter_cb _hidl_cb) {
832     hardware::hidl_vec<int32_t> values;
833     EvsResult status = EvsResult::INVALID_ARG;
834     if (mHalCamera.size() > 1) {
835         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
836         _hidl_cb(status, values);
837         return Void();
838     }
839 
840     auto pHwCamera = mHalCamera.begin()->second.promote();
841     if (pHwCamera == nullptr) {
842         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
843         _hidl_cb(status, values);
844         return Void();
845     }
846 
847     int32_t value;
848     status = pHwCamera->getParameter(id, &value);
849 
850     values.resize(1);
851     values[0] = value;
852     _hidl_cb(status, values);
853 
854     return Void();
855 }
856 
setExtendedInfo_1_1(uint32_t opaqueIdentifier,const hidl_vec<uint8_t> & opaqueValue)857 Return<EvsResult> VirtualCamera::setExtendedInfo_1_1(uint32_t opaqueIdentifier,
858                                                      const hidl_vec<uint8_t>& opaqueValue) {
859     hardware::hidl_vec<int32_t> values;
860     if (mHalCamera.size() > 1) {
861         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
862         return EvsResult::INVALID_ARG;
863     }
864 
865     auto pHwCamera = mHalCamera.begin()->second.promote();
866     if (pHwCamera == nullptr) {
867         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
868         return EvsResult::INVALID_ARG;
869     } else {
870         auto hwCamera = IEvsCamera_1_1::castFrom(pHwCamera->getHwCamera()).withDefault(nullptr);
871         if (hwCamera != nullptr) {
872             return hwCamera->setExtendedInfo_1_1(opaqueIdentifier, opaqueValue);
873         } else {
874             LOG(ERROR) << "Underlying hardware camera does not implement v1.1 interfaces.";
875             return EvsResult::INVALID_ARG;
876         }
877     }
878 }
879 
getExtendedInfo_1_1(uint32_t opaqueIdentifier,getExtendedInfo_1_1_cb _hidl_cb)880 Return<void> VirtualCamera::getExtendedInfo_1_1(uint32_t opaqueIdentifier,
881                                                 getExtendedInfo_1_1_cb _hidl_cb) {
882     hardware::hidl_vec<uint8_t> values;
883     EvsResult status = EvsResult::INVALID_ARG;
884     if (mHalCamera.size() > 1) {
885         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
886         _hidl_cb(status, values);
887         return Void();
888     }
889 
890     auto pHwCamera = mHalCamera.begin()->second.promote();
891     if (pHwCamera == nullptr) {
892         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
893         _hidl_cb(status, values);
894     } else {
895         auto hwCamera = IEvsCamera_1_1::castFrom(pHwCamera->getHwCamera()).withDefault(nullptr);
896         if (hwCamera != nullptr) {
897             hwCamera->getExtendedInfo_1_1(opaqueIdentifier, _hidl_cb);
898         } else {
899             LOG(ERROR) << "Underlying hardware camera does not implement v1.1 interfaces.";
900             _hidl_cb(status, values);
901         }
902     }
903 
904     return Void();
905 }
906 
importExternalBuffers(const hidl_vec<BufferDesc_1_1> & buffers,importExternalBuffers_cb _hidl_cb)907 Return<void> VirtualCamera::importExternalBuffers(const hidl_vec<BufferDesc_1_1>& buffers,
908                                                   importExternalBuffers_cb _hidl_cb) {
909     if (mHalCamera.size() > 1) {
910         LOG(WARNING) << "Logical camera device does not support " << __FUNCTION__;
911         _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
912         return {};
913     }
914 
915     auto pHwCamera = mHalCamera.begin()->second.promote();
916     if (pHwCamera == nullptr) {
917         LOG(WARNING) << "Camera device " << mHalCamera.begin()->first << " is not alive.";
918         _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
919         return {};
920     }
921 
922     int delta = 0;
923     if (!pHwCamera->changeFramesInFlight(buffers, &delta)) {
924         LOG(ERROR) << "Failed to add extenral capture buffers.";
925         _hidl_cb(EvsResult::UNDERLYING_SERVICE_ERROR, 0);
926         return {};
927     }
928 
929     mFramesAllowed += delta;
930     _hidl_cb(EvsResult::OK, delta);
931     return {};
932 }
933 
toString(const char * indent) const934 std::string VirtualCamera::toString(const char* indent) const {
935     std::string buffer;
936     StringAppendF(&buffer,
937                   "%sLogical camera device: %s\n"
938                   "%sFramesAllowed: %u\n"
939                   "%sFrames in use:\n",
940                   indent, mHalCamera.size() > 1 ? "T" : "F", indent, mFramesAllowed, indent);
941 
942     std::string next_indent(indent);
943     next_indent += "\t";
944     std::lock_guard<std::recursive_mutex> lock(mFramesHeldMutex);
945     for (auto&& [id, queue] : mFramesHeld) {
946         StringAppendF(&buffer, "%s%s: %d\n", next_indent.c_str(), id.c_str(),
947                       static_cast<int>(queue.size()));
948     }
949     StringAppendF(&buffer, "%sCurrent stream state: %d\n", indent, mStreamState);
950 
951     return buffer;
952 }
953 
954 }  // namespace android::automotive::evs::V1_1::implementation
955