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 "Enumerator.h"
18 #include "HalCamera.h"
19 #include "VirtualCamera.h"
20 
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <android-base/strings.h>
24 
25 namespace android {
26 namespace automotive {
27 namespace evs {
28 namespace V1_1 {
29 namespace implementation {
30 
31 
32 // TODO(changyeon):
33 // We need to hook up death monitoring to detect stream death so we can attempt a reconnect
34 
35 using ::android::base::StringAppendF;
36 using ::android::base::WriteStringToFd;
37 
~HalCamera()38 HalCamera::~HalCamera() {
39     // Reports the usage statistics before the destruction
40     // EvsUsageStatsReported atom is defined in
41     // frameworks/base/cmds/statsd/src/atoms.proto
42     mUsageStats->writeStats();
43 }
44 
makeVirtualCamera()45 sp<VirtualCamera> HalCamera::makeVirtualCamera() {
46 
47     // Create the client camera interface object
48     std::vector<sp<HalCamera>> sourceCameras;
49     sourceCameras.reserve(1);
50     sourceCameras.emplace_back(this);
51     sp<VirtualCamera> client = new VirtualCamera(sourceCameras);
52     if (client == nullptr) {
53         LOG(ERROR) << "Failed to create client camera object";
54         return nullptr;
55     }
56 
57     if (!ownVirtualCamera(client)) {
58         LOG(ERROR) << "Failed to own a client camera object";
59         client = nullptr;
60     }
61 
62     return client;
63 }
64 
65 
ownVirtualCamera(sp<VirtualCamera> virtualCamera)66 bool HalCamera::ownVirtualCamera(sp<VirtualCamera> virtualCamera) {
67 
68     if (virtualCamera == nullptr) {
69         LOG(ERROR) << "Failed to create virtualCamera camera object";
70         return false;
71     }
72 
73     // Make sure we have enough buffers available for all our clients
74     if (!changeFramesInFlight(virtualCamera->getAllowedBuffers())) {
75         // Gah!  We couldn't get enough buffers, so we can't support this virtualCamera
76         // Null the pointer, dropping our reference, thus destroying the virtualCamera object
77         return false;
78     }
79 
80     if (mSyncSupported) {
81         // Create a timeline
82         std::lock_guard<std::mutex> lock(mFrameMutex);
83         auto timeline = make_unique<UniqueTimeline>(0);
84         if (timeline != nullptr) {
85             mTimelines[(uint64_t)virtualCamera.get()] = std::move(timeline);
86         } else {
87             LOG(WARNING) << "Failed to create a timeline. "
88                          << "Client " << std::hex << virtualCamera.get()
89                          << " will use v1.0 frame delivery mechanism.";
90         }
91     }
92 
93     // Add this virtualCamera to our ownership list via weak pointer
94     mClients.emplace_back(virtualCamera);
95 
96     // Update statistics
97     mUsageStats->updateNumClients(mClients.size());
98 
99     return true;
100 }
101 
102 
disownVirtualCamera(sp<VirtualCamera> virtualCamera)103 void HalCamera::disownVirtualCamera(sp<VirtualCamera> virtualCamera) {
104     // Ignore calls with null pointers
105     if (virtualCamera.get() == nullptr) {
106         LOG(WARNING) << "Ignoring disownVirtualCamera call with null pointer";
107         return;
108     }
109 
110     // Remove the virtual camera from our client list
111     unsigned clientCount = mClients.size();
112     mClients.remove(virtualCamera);
113     if (clientCount != mClients.size() + 1) {
114         LOG(ERROR) << "Couldn't find camera in our client list to remove it";
115     }
116 
117     // Recompute the number of buffers required with the target camera removed from the list
118     if (!changeFramesInFlight(0)) {
119         LOG(ERROR) << "Error when trying to reduce the in flight buffer count";
120     }
121 
122     // Update statistics
123     mUsageStats->updateNumClients(mClients.size());
124 }
125 
126 
changeFramesInFlight(int delta)127 bool HalCamera::changeFramesInFlight(int delta) {
128     // Walk all our clients and count their currently required frames
129     unsigned bufferCount = 0;
130     for (auto&& client :  mClients) {
131         sp<VirtualCamera> virtCam = client.promote();
132         if (virtCam != nullptr) {
133             bufferCount += virtCam->getAllowedBuffers();
134         }
135     }
136 
137     // Add the requested delta
138     bufferCount += delta;
139 
140     // Never drop below 1 buffer -- even if all client cameras get closed
141     if (bufferCount < 1) {
142         bufferCount = 1;
143     }
144 
145     // Ask the hardware for the resulting buffer count
146     Return<EvsResult> result = mHwCamera->setMaxFramesInFlight(bufferCount);
147     bool success = (result.isOk() && result == EvsResult::OK);
148 
149     // Update the size of our array of outstanding frame records
150     if (success) {
151         std::vector<FrameRecord> newRecords;
152         newRecords.reserve(bufferCount);
153 
154         // Copy and compact the old records that are still active
155         for (const auto& rec : mFrames) {
156             if (rec.refCount > 0) {
157                 newRecords.emplace_back(rec);
158             }
159         }
160         if (newRecords.size() > (unsigned)bufferCount) {
161             LOG(WARNING) << "We found more frames in use than requested.";
162         }
163 
164         mFrames.swap(newRecords);
165     }
166 
167     return success;
168 }
169 
170 
changeFramesInFlight(const hidl_vec<BufferDesc_1_1> & buffers,int * delta)171 bool HalCamera::changeFramesInFlight(const hidl_vec<BufferDesc_1_1>& buffers,
172                                      int* delta) {
173     // Return immediately if a list is empty.
174     if (buffers.size() < 1) {
175         LOG(DEBUG) << "No external buffers to add.";
176         return true;
177     }
178 
179     // Walk all our clients and count their currently required frames
180     auto bufferCount = 0;
181     for (auto&& client :  mClients) {
182         sp<VirtualCamera> virtCam = client.promote();
183         if (virtCam != nullptr) {
184             bufferCount += virtCam->getAllowedBuffers();
185         }
186     }
187 
188     EvsResult status = EvsResult::OK;
189     // Ask the hardware for the resulting buffer count
190     mHwCamera->importExternalBuffers(buffers,
191                                      [&](auto result, auto added) {
192                                          status = result;
193                                          *delta = added;
194                                      });
195     if (status != EvsResult::OK) {
196         LOG(ERROR) << "Failed to add external capture buffers.";
197         return false;
198     }
199 
200     bufferCount += *delta;
201 
202     // Update the size of our array of outstanding frame records
203     std::vector<FrameRecord> newRecords;
204     newRecords.reserve(bufferCount);
205 
206     // Copy and compact the old records that are still active
207     for (const auto& rec : mFrames) {
208         if (rec.refCount > 0) {
209             newRecords.emplace_back(rec);
210         }
211     }
212 
213     if (newRecords.size() > (unsigned)bufferCount) {
214         LOG(WARNING) << "We found more frames in use than requested.";
215     }
216 
217     mFrames.swap(newRecords);
218 
219     return true;
220 }
221 
222 
requestNewFrame(sp<VirtualCamera> client,const int64_t lastTimestamp)223 UniqueFence HalCamera::requestNewFrame(sp<VirtualCamera> client,
224                                        const int64_t lastTimestamp) {
225     if (!mSyncSupported) {
226         LOG(ERROR) << "This HalCamera does not support a fence-based "
227                    << "frame delivery.";
228         return {};
229     }
230 
231     FrameRequest req;
232     req.client = client;
233     req.timestamp = lastTimestamp;
234 
235     const uint64_t id = (uint64_t)client.get();
236 
237     std::lock_guard<std::mutex> lock(mFrameMutex);
238 
239     mTimelines[id]->BumpFenceEventCounter();
240     UniqueFence fence = mTimelines[id]->CreateFence("FrameFence");
241 
242     mNextRequests->push_back(req);
243 
244     return fence.Dup();
245 }
246 
247 
clientStreamStarting()248 Return<EvsResult> HalCamera::clientStreamStarting() {
249     Return<EvsResult> result = EvsResult::OK;
250 
251     if (mStreamState == STOPPED) {
252         mStreamState = RUNNING;
253         result = mHwCamera->startVideoStream(this);
254     }
255 
256     return result;
257 }
258 
259 
clientStreamEnding(const VirtualCamera * client)260 void HalCamera::clientStreamEnding(const VirtualCamera* client) {
261     {
262         std::lock_guard<std::mutex> lock(mFrameMutex);
263         auto itReq = mNextRequests->begin();
264         while (itReq != mNextRequests->end()) {
265             if (itReq->client == client) {
266                 break;
267             } else {
268                 ++itReq;
269             }
270         }
271 
272         const uint64_t clientId = reinterpret_cast<const uint64_t>(client);
273         if (itReq != mNextRequests->end()) {
274             mNextRequests->erase(itReq);
275 
276             // Signal a pending fence and delete associated timeline.
277             if (mTimelines.find(clientId) != mTimelines.end()) {
278                 mTimelines[clientId]->BumpTimelineEventCounter();
279                 mTimelines.erase(clientId);
280             }
281         }
282 
283         auto itCam = mClients.begin();
284         while (itCam != mClients.end()) {
285             if (itCam->promote() == client) {
286                 break;
287             } else {
288                 ++itCam;
289             }
290         }
291 
292         if (itCam != mClients.end()) {
293             // Remove a client, which requested to stop, from the list.
294             mClients.erase(itCam);
295         }
296     }
297 
298     // Do we still have a running client?
299     bool stillRunning = false;
300     for (auto&& client : mClients) {
301         sp<VirtualCamera> virtCam = client.promote();
302         if (virtCam != nullptr) {
303             stillRunning |= virtCam->isStreaming();
304         }
305     }
306 
307     // If not, then stop the hardware stream
308     if (!stillRunning) {
309         mStreamState = STOPPING;
310         mHwCamera->stopVideoStream();
311     }
312 }
313 
314 
doneWithFrame(const BufferDesc_1_0 & buffer)315 Return<void> HalCamera::doneWithFrame(const BufferDesc_1_0& buffer) {
316     // Find this frame in our list of outstanding frames
317     unsigned i;
318     for (i = 0; i < mFrames.size(); i++) {
319         if (mFrames[i].frameId == buffer.bufferId) {
320             break;
321         }
322     }
323     if (i == mFrames.size()) {
324         LOG(ERROR) << "We got a frame back with an ID we don't recognize!";
325     } else {
326         // Are there still clients using this buffer?
327         mFrames[i].refCount--;
328         if (mFrames[i].refCount <= 0) {
329             // Since all our clients are done with this buffer, return it to the device layer
330             mHwCamera->doneWithFrame(buffer);
331 
332             // Counts a returned buffer
333             mUsageStats->framesReturned();
334         }
335     }
336 
337     return Void();
338 }
339 
340 
doneWithFrame(const BufferDesc_1_1 & buffer)341 Return<void> HalCamera::doneWithFrame(const BufferDesc_1_1& buffer) {
342     // Find this frame in our list of outstanding frames
343     unsigned i;
344     for (i = 0; i < mFrames.size(); i++) {
345         if (mFrames[i].frameId == buffer.bufferId) {
346             break;
347         }
348     }
349     if (i == mFrames.size()) {
350         LOG(ERROR) << "We got a frame back with an ID we don't recognize!";
351     } else {
352         // Are there still clients using this buffer?
353         mFrames[i].refCount--;
354         if (mFrames[i].refCount <= 0) {
355             // Since all our clients are done with this buffer, return it to the device layer
356             hardware::hidl_vec<BufferDesc_1_1> returnedBuffers;
357             returnedBuffers.resize(1);
358             returnedBuffers[0] = buffer;
359             mHwCamera->doneWithFrame_1_1(returnedBuffers);
360 
361             // Counts a returned buffer
362             mUsageStats->framesReturned(returnedBuffers);
363         }
364     }
365 
366     return Void();
367 }
368 
369 
370 // Methods from ::android::hardware::automotive::evs::V1_0::IEvsCameraStream follow.
deliverFrame(const BufferDesc_1_0 & buffer)371 Return<void> HalCamera::deliverFrame(const BufferDesc_1_0& buffer) {
372     /* Frames are delivered via deliverFrame_1_1 callback for clients that implement
373      * IEvsCameraStream v1.1 interfaces and therefore this method must not be
374      * used.
375      */
376     LOG(INFO) << "A delivered frame from EVS v1.0 HW module is rejected.";
377     mHwCamera->doneWithFrame(buffer);
378 
379     // Reports a received and returned buffer
380     mUsageStats->framesReceived();
381     mUsageStats->framesReturned();
382 
383     return Void();
384 }
385 
386 
387 // Methods from ::android::hardware::automotive::evs::V1_1::IEvsCameraStream follow.
deliverFrame_1_1(const hardware::hidl_vec<BufferDesc_1_1> & buffer)388 Return<void> HalCamera::deliverFrame_1_1(const hardware::hidl_vec<BufferDesc_1_1>& buffer) {
389     LOG(VERBOSE) << "Received a frame";
390     // Frames are being forwarded to v1.1 clients only who requested new frame.
391     const auto timestamp = buffer[0].timestamp;
392     // TODO(b/145750636): For now, we are using a approximately half of 1 seconds / 30 frames = 33ms
393     //           but this must be derived from current framerate.
394     constexpr int64_t kThreshold = 16 * 1e+3; // ms
395     unsigned frameDeliveriesV1 = 0;
396     if (mSyncSupported) {
397         std::lock_guard<std::mutex> lock(mFrameMutex);
398         std::swap(mCurrentRequests, mNextRequests);
399         while (!mCurrentRequests->empty()) {
400             auto req = mCurrentRequests->front(); mCurrentRequests->pop_front();
401             sp<VirtualCamera> vCam = req.client.promote();
402             if (vCam == nullptr) {
403                 // Ignore a client already dead.
404                 continue;
405             } else if (timestamp - req.timestamp < kThreshold) {
406                 // Skip current frame because it arrives too soon.
407                 LOG(DEBUG) << "Skips a frame from " << getId();
408                 mNextRequests->push_back(req);
409 
410                 // Reports a skipped frame
411                 mUsageStats->framesSkippedToSync();
412             } else if (vCam != nullptr && vCam->deliverFrame(buffer[0])) {
413                 // Forward a frame and move a timeline.
414                 LOG(DEBUG) << getId() << " forwarded the buffer #" << buffer[0].bufferId;
415                 mTimelines[(uint64_t)vCam.get()]->BumpTimelineEventCounter();
416                 ++frameDeliveriesV1;
417             }
418         }
419     }
420 
421     // Reports the number of received buffers
422     mUsageStats->framesReceived(buffer);
423 
424     // Frames are being forwarded to active v1.0 clients and v1.1 clients if we
425     // failed to create a timeline.
426     unsigned frameDeliveries = 0;
427     for (auto&& client : mClients) {
428         sp<VirtualCamera> vCam = client.promote();
429         if (vCam == nullptr || (mSyncSupported && vCam->getVersion() > 0)) {
430             continue;
431         }
432 
433         if (vCam->deliverFrame(buffer[0])) {
434             ++frameDeliveries;
435         }
436     }
437 
438     frameDeliveries += frameDeliveriesV1;
439     if (frameDeliveries < 1) {
440         // If none of our clients could accept the frame, then return it
441         // right away.
442         LOG(INFO) << "Trivially rejecting frame (" << buffer[0].bufferId
443                   << ") from " << getId() << " with no acceptance";
444         mHwCamera->doneWithFrame_1_1(buffer);
445 
446         // Reports a returned buffer
447         mUsageStats->framesReturned(buffer);
448     } else {
449         // Add an entry for this frame in our tracking list.
450         unsigned i;
451         for (i = 0; i < mFrames.size(); ++i) {
452             if (mFrames[i].refCount == 0) {
453                 break;
454             }
455         }
456 
457         if (i == mFrames.size()) {
458             mFrames.emplace_back(buffer[0].bufferId);
459         } else {
460             mFrames[i].frameId = buffer[0].bufferId;
461         }
462         mFrames[i].refCount = frameDeliveries;
463     }
464 
465     return Void();
466 }
467 
468 
notify(const EvsEventDesc & event)469 Return<void> HalCamera::notify(const EvsEventDesc& event) {
470     LOG(DEBUG) << "Received an event id: " << static_cast<int32_t>(event.aType);
471     if(event.aType == EvsEventType::STREAM_STOPPED) {
472         // This event happens only when there is no more active client.
473         if (mStreamState != STOPPING) {
474             LOG(WARNING) << "Stream stopped unexpectedly";
475         }
476 
477         mStreamState = STOPPED;
478     }
479 
480     // Forward all other events to the clients
481     for (auto&& client : mClients) {
482         sp<VirtualCamera> vCam = client.promote();
483         if (vCam != nullptr) {
484             if (!vCam->notify(event)) {
485                 LOG(INFO) << "Failed to forward an event";
486             }
487         }
488     }
489 
490     return Void();
491 }
492 
493 
setMaster(sp<VirtualCamera> virtualCamera)494 Return<EvsResult> HalCamera::setMaster(sp<VirtualCamera> virtualCamera) {
495     if (mMaster == nullptr) {
496         LOG(DEBUG) << __FUNCTION__
497                    << ": " << virtualCamera.get() << " becomes a master.";
498         mMaster = virtualCamera;
499         return EvsResult::OK;
500     } else {
501         LOG(INFO) << "This camera already has a master client.";
502         return EvsResult::OWNERSHIP_LOST;
503     }
504 }
505 
506 
forceMaster(sp<VirtualCamera> virtualCamera)507 Return<EvsResult> HalCamera::forceMaster(sp<VirtualCamera> virtualCamera) {
508     sp<VirtualCamera> prevMaster = mMaster.promote();
509     if (prevMaster == virtualCamera) {
510         LOG(DEBUG) << "Client " << virtualCamera.get()
511                    << " is already a master client";
512     } else {
513         mMaster = virtualCamera;
514         if (prevMaster != nullptr) {
515             LOG(INFO) << "High priority client " << virtualCamera.get()
516                       << " steals a master role from " << prevMaster.get();
517 
518             /* Notify a previous master client the loss of a master role */
519             EvsEventDesc event;
520             event.aType = EvsEventType::MASTER_RELEASED;
521             if (!prevMaster->notify(event)) {
522                 LOG(ERROR) << "Fail to deliver a master role lost notification";
523             }
524         }
525     }
526 
527     return EvsResult::OK;
528 }
529 
530 
unsetMaster(sp<VirtualCamera> virtualCamera)531 Return<EvsResult> HalCamera::unsetMaster(sp<VirtualCamera> virtualCamera) {
532     if (mMaster.promote() != virtualCamera) {
533         return EvsResult::INVALID_ARG;
534     } else {
535         LOG(INFO) << "Unset a master camera client";
536         mMaster = nullptr;
537 
538         /* Notify other clients that a master role becomes available. */
539         EvsEventDesc event;
540         event.aType = EvsEventType::MASTER_RELEASED;
541         auto cbResult = this->notify(event);
542         if (!cbResult.isOk()) {
543             LOG(ERROR) << "Fail to deliver a parameter change notification";
544         }
545 
546         return EvsResult::OK;
547     }
548 }
549 
550 
setParameter(sp<VirtualCamera> virtualCamera,CameraParam id,int32_t & value)551 Return<EvsResult> HalCamera::setParameter(sp<VirtualCamera> virtualCamera,
552                                           CameraParam id, int32_t& value) {
553     EvsResult result = EvsResult::INVALID_ARG;
554     if (virtualCamera == mMaster.promote()) {
555         mHwCamera->setIntParameter(id, value,
556                                    [&result, &value](auto status, auto readValue) {
557                                        result = status;
558                                        value = readValue[0];
559                                    });
560 
561         if (result == EvsResult::OK) {
562             /* Notify a parameter change */
563             EvsEventDesc event;
564             event.aType = EvsEventType::PARAMETER_CHANGED;
565             event.payload[0] = static_cast<uint32_t>(id);
566             event.payload[1] = static_cast<uint32_t>(value);
567             auto cbResult = this->notify(event);
568             if (!cbResult.isOk()) {
569                 LOG(ERROR) << "Fail to deliver a parameter change notification";
570             }
571         }
572     } else {
573         LOG(WARNING) << "A parameter change request from a non-master client is declined.";
574 
575         /* Read a current value of a requested camera parameter */
576         getParameter(id, value);
577     }
578 
579     return result;
580 }
581 
582 
getParameter(CameraParam id,int32_t & value)583 Return<EvsResult> HalCamera::getParameter(CameraParam id, int32_t& value) {
584     EvsResult result = EvsResult::OK;
585     mHwCamera->getIntParameter(id, [&result, &value](auto status, auto readValue) {
586                                        result = status;
587                                        if (result == EvsResult::OK) {
588                                            value = readValue[0];
589                                        }
590     });
591 
592     return result;
593 }
594 
595 
getStats() const596 CameraUsageStatsRecord HalCamera::getStats() const {
597     return mUsageStats->snapshot();
598 }
599 
600 
getStreamConfiguration() const601 Stream HalCamera::getStreamConfiguration() const {
602     return mStreamConfig;
603 }
604 
605 
toString(const char * indent) const606 std::string HalCamera::toString(const char* indent) const {
607     std::string buffer;
608 
609     const auto timeElapsedMs = android::uptimeMillis() - mTimeCreatedMs;
610     StringAppendF(&buffer, "%sCreated: @%" PRId64 " (elapsed %" PRId64 " ms)\n",
611                            indent, mTimeCreatedMs, timeElapsedMs);
612 
613     std::string double_indent(indent);
614     double_indent += indent;
615     buffer += CameraUsageStats::toString(getStats(), double_indent.c_str());
616     for (auto&& client : mClients) {
617         auto handle = client.promote();
618         if (!handle) {
619             continue;
620         }
621 
622         StringAppendF(&buffer, "%sClient %p\n",
623                                indent, handle.get());
624         buffer += handle->toString(double_indent.c_str());
625     }
626 
627     StringAppendF(&buffer, "%sMaster client: %p\n"
628                            "%sSynchronization support: %s\n",
629                            indent, mMaster.promote().get(),
630                            indent, mSyncSupported ? "T":"F");
631 
632     buffer += HalCamera::toString(mStreamConfig, indent);
633 
634     return buffer;
635 }
636 
637 
toString(Stream configuration,const char * indent)638 std::string HalCamera::toString(Stream configuration, const char* indent) {
639     std::string streamInfo;
640     std::string double_indent(indent);
641     double_indent += indent;
642     StringAppendF(&streamInfo, "%sActive Stream Configuration\n"
643                                "%sid: %d\n"
644                                "%swidth: %d\n"
645                                "%sheight: %d\n"
646                                "%sformat: 0x%X\n"
647                                "%susage: 0x%" PRIx64 "\n"
648                                "%srotation: 0x%X\n\n",
649                                indent,
650                                double_indent.c_str(), configuration.id,
651                                double_indent.c_str(), configuration.width,
652                                double_indent.c_str(), configuration.height,
653                                double_indent.c_str(), configuration.format,
654                                double_indent.c_str(), configuration.usage,
655                                double_indent.c_str(), configuration.rotation);
656 
657     return streamInfo;
658 }
659 
660 
661 } // namespace implementation
662 } // namespace V1_1
663 } // namespace evs
664 } // namespace automotive
665 } // namespace android
666