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