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