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